`include "constants.vh"

//`default_nettype none
`define ALU_OP_WIDTH 4

`define ALU_OP_ADD  `ALU_OP_WIDTH'd0
`define ALU_OP_SLL  `ALU_OP_WIDTH'd1
`define ALU_OP_XOR  `ALU_OP_WIDTH'd4
`define ALU_OP_OR   `ALU_OP_WIDTH'd6
`define ALU_OP_AND  `ALU_OP_WIDTH'd7
`define ALU_OP_SRL  `ALU_OP_WIDTH'd5
`define ALU_OP_SEQ  `ALU_OP_WIDTH'd8
`define ALU_OP_SNE  `ALU_OP_WIDTH'd9
`define ALU_OP_SUB  `ALU_OP_WIDTH'd10
`define ALU_OP_SRA  `ALU_OP_WIDTH'd11
`define ALU_OP_SLT  `ALU_OP_WIDTH'd12
`define ALU_OP_SGE  `ALU_OP_WIDTH'd13
`define ALU_OP_SLTU `ALU_OP_WIDTH'd14
`define ALU_OP_SGEU `ALU_OP_WIDTH'd15
//Register File
`define REG_SEL 5
//`define REG_NUM 2**`REG_SEL
`define REG_NUM 32

//Instruction
`define IMM_TYPE_WIDTH 2
`define IMM_I `IMM_TYPE_WIDTH'd0
`define IMM_S `IMM_TYPE_WIDTH'd1
`define IMM_U `IMM_TYPE_WIDTH'd2
`define IMM_J `IMM_TYPE_WIDTH'd3

//Important Wire
`define DATA_LEN 32
`define INSN_LEN 32
`define ADDR_LEN 32
`define ISSUE_NUM 2
`define ENTRY_POINT `ADDR_LEN'h0
//`define REQDATA_LEN 2

//Decoder
`define RS_ENT_SEL 3
`define RS_ENT_ALU 1
`define RS_ENT_BRANCH 2
`define RS_ENT_JAL `RS_ENT_BRANCH
`define RS_ENT_JALR `RS_ENT_BRANCH
`define RS_ENT_MUL 3
`define RS_ENT_DIV 3
`define RS_ENT_LDST 4

//RS
`define ALU_ENT_SEL 3
`define ALU_ENT_NUM 8
`define BRANCH_ENT_SEL 2
`define BRANCH_ENT_NUM 4
`define LDST_ENT_SEL 2
`define LDST_ENT_NUM 4
//`define LDST_ENT_SEL 3
//`define LDST_ENT_NUM 8
`define MUL_ENT_SEL 1
`define MUL_ENT_NUM 2

//STOREBUFFER
`define STBUF_ENT_SEL 5
`define STBUF_ENT_NUM 32

//BTB
`define BTB_IDX_SEL 9
`define BTB_IDX_NUM 512
//`define BTB_IDX_NUM 2**`BTB_IDX_SEL
//`define BTB_TAG_LEN `ADDR_LEN-3-`BTB_IDX_SEL
`define BTB_TAG_LEN 20

//Gshare
`define GSH_BHR_LEN 10
`define GSH_PHT_SEL 10
`define GSH_PHT_NUM 1024
//`define GSH_PHT_NUM 2**`GSH_PHT_SEL

//TagGenerator

//`define SPECTAG_LEN 1+`BRANCH_ENT_NUM
`define SPECTAG_LEN 5
//`define BRDEPTH_LEN `SPECTAG_LEN
`define BRDEPTH_LEN 5

//Re-Order Buffer
`define ROB_SEL 6
//`define ROB_NUM 2**`ROB_SEL
`define ROB_NUM 64
`define RRF_SEL `ROB_SEL
`define RRF_NUM `ROB_NUM

//src_a
`define SRC_A_SEL_WIDTH 2
`define SRC_A_RS1  `SRC_A_SEL_WIDTH'd0
`define SRC_A_PC   `SRC_A_SEL_WIDTH'd1
`define SRC_A_ZERO `SRC_A_SEL_WIDTH'd2

//src_b
`define SRC_B_SEL_WIDTH 2
`define SRC_B_RS2  `SRC_B_SEL_WIDTH'd0
`define SRC_B_IMM  `SRC_B_SEL_WIDTH'd1
`define SRC_B_FOUR `SRC_B_SEL_WIDTH'd2
`define SRC_B_ZERO `SRC_B_SEL_WIDTH'd3

`define MEM_TYPE_WIDTH 3
`define MEM_TYPE_LB  `MEM_TYPE_WIDTH'd0
`define MEM_TYPE_LH  `MEM_TYPE_WIDTH'd1
`define MEM_TYPE_LW  `MEM_TYPE_WIDTH'd2
`define MEM_TYPE_LD  `MEM_TYPE_WIDTH'd3
`define MEM_TYPE_LBU `MEM_TYPE_WIDTH'd4
`define MEM_TYPE_LHU `MEM_TYPE_WIDTH'd5
`define MEM_TYPE_LWU `MEM_TYPE_WIDTH'd6

`define MEM_TYPE_SB  `MEM_TYPE_WIDTH'd0
`define MEM_TYPE_SH  `MEM_TYPE_WIDTH'd1
`define MEM_TYPE_SW  `MEM_TYPE_WIDTH'd2
`define MEM_TYPE_SD  `MEM_TYPE_WIDTH'd3

`define MD_OP_WIDTH 2
`define MD_OP_MUL `MD_OP_WIDTH'd0
`define MD_OP_DIV `MD_OP_WIDTH'd1
`define MD_OP_REM `MD_OP_WIDTH'd2

`define MD_OUT_SEL_WIDTH 2
`define MD_OUT_LO  `MD_OUT_SEL_WIDTH'd0
`define MD_OUT_HI  `MD_OUT_SEL_WIDTH'd1
`define MD_OUT_REM `MD_OUT_SEL_WIDTH'd2

// Width-related constants
`define INST_WIDTH     32
`define REG_ADDR_WIDTH  5
`define XPR_LEN        32
`define DOUBLE_XPR_LEN 64
`define LOG2_XPR_LEN    5
`define SHAMT_WIDTH     5

`define RV_NOP `INST_WIDTH'b0010011

// Opcodes

`define RV32_LOAD     7'b0000011
`define RV32_STORE    7'b0100011
`define RV32_MADD     7'b1000011
`define RV32_BRANCH   7'b1100011

`define RV32_LOAD_FP  7'b0000111
`define RV32_STORE_FP 7'b0100111 
`define RV32_MSUB     7'b1000111
`define RV32_JALR     7'b1100111

`define RV32_CUSTOM_0 7'b0001011
`define RV32_CUSTOM_1 7'b0101011
`define RV32_NMSUB    7'b1001011
// 7'b1101011 is reserved

`define RV32_MISC_MEM 7'b0001111
`define RV32_AMO      7'b0101111
`define RV32_NMADD    7'b1001111
`define RV32_JAL      7'b1101111

`define RV32_OP_IMM   7'b0010011
`define RV32_OP       7'b0110011
`define RV32_OP_FP    7'b1010011
`define RV32_SYSTEM   7'b1110011

`define RV32_AUIPC    7'b0010111
`define RV32_LUI      7'b0110111
// 7'b1010111 is reserved
// 7'b1110111 is reserved

// 7'b0011011 is RV64-specific
// 7'b0111011 is RV64-specific
`define RV32_CUSTOM_2 7'b1011011
`define RV32_CUSTOM_3 7'b1111011

// Arithmetic FUNCT3 encodings

`define RV32_FUNCT3_ADD_SUB 0
`define RV32_FUNCT3_SLL     1
`define RV32_FUNCT3_SLT     2
`define RV32_FUNCT3_SLTU    3
`define RV32_FUNCT3_XOR     4
`define RV32_FUNCT3_SRA_SRL 5
`define RV32_FUNCT3_OR      6
`define RV32_FUNCT3_AND     7

// Branch FUNCT3 encodings

`define RV32_FUNCT3_BEQ  0
`define RV32_FUNCT3_BNE  1
`define RV32_FUNCT3_BLT  4
`define RV32_FUNCT3_BGE  5
`define RV32_FUNCT3_BLTU 6
`define RV32_FUNCT3_BGEU 7

// MISC-MEM FUNCT3 encodings
`define RV32_FUNCT3_FENCE   0
`define RV32_FUNCT3_FENCE_I 1

// SYSTEM FUNCT3 encodings

`define RV32_FUNCT3_PRIV   0
`define RV32_FUNCT3_CSRRW  1
`define RV32_FUNCT3_CSRRS  2
`define RV32_FUNCT3_CSRRC  3
`define RV32_FUNCT3_CSRRWI 5
`define RV32_FUNCT3_CSRRSI 6
`define RV32_FUNCT3_CSRRCI 7

// PRIV FUNCT12 encodings

`define RV32_FUNCT12_ECALL  12'b000000000000
`define RV32_FUNCT12_EBREAK 12'b000000000001
`define RV32_FUNCT12_ERET   12'b000100000000

// RV32M encodings
`define RV32_FUNCT7_MUL_DIV 7'd1

`define RV32_FUNCT3_MUL    3'd0
`define RV32_FUNCT3_MULH   3'd1
`define RV32_FUNCT3_MULHSU 3'd2
`define RV32_FUNCT3_MULHU  3'd3
`define RV32_FUNCT3_DIV    3'd4
`define RV32_FUNCT3_DIVU   3'd5
`define RV32_FUNCT3_REM    3'd6
`define RV32_FUNCT3_REMU   3'd7

  
module alloc_issue_ino  #(
			  parameter ENTSEL = 2,
			  parameter ENTNUM = 4
			  )
   (
    input wire 		     clk,
    input wire 		     reset,
    input wire [1:0] 	     reqnum,
    input wire [ENTNUM-1:0]  busyvec,
    input wire [ENTNUM-1:0]  prbusyvec_next,
    input wire [ENTNUM-1:0]  readyvec,
    input wire 		     prmiss,
    input wire 		     exunit_busynext,
    input wire 		     stall_DP,
    input wire 		     kill_DP,
    output reg [ENTSEL-1:0]  allocptr,
    output wire 	     allocatable,
    output wire [ENTSEL-1:0] issueptr,
    output wire 	     issuevalid
   );


   wire [ENTSEL-1:0] 	    allocptr2 = allocptr + 1;
   wire [ENTSEL-1:0] 	    b0;
   wire [ENTSEL-1:0] 	    e0;
   wire [ENTSEL-1:0] 	    b1;
   wire [ENTSEL-1:0] 	    e1;
   wire 		    notfull;

   wire [ENTSEL-1:0] 	    ne1;
   wire [ENTSEL-1:0] 	    nb0;
   wire [ENTSEL-1:0] 	    nb1;
   wire 		    notfull_next;
   
   search_begin #(ENTSEL, ENTNUM) sb1(
				      .in(busyvec),
				      .out(b1),
				      .en()
				      );
   
   search_end #(ENTSEL, ENTNUM) se1(
				    .in(busyvec),
				    .out(e1),
				    .en()
				    );

   search_end #(ENTSEL, ENTNUM) se0(
				    .in(~busyvec),
				    .out(e0),
				    .en(notfull)
				    );

   search_begin #(ENTSEL, ENTNUM) snb1(
				       .in(prbusyvec_next),
				       .out(nb1),
				       .en()
				       );
   
   search_end #(ENTSEL, ENTNUM) sne1(
				     .in(prbusyvec_next),
				     .out(ne1),
				     .en()
				     );

   search_begin #(ENTSEL, ENTNUM) snb0(
				       .in(~prbusyvec_next),
				       .out(nb0),
				       .en(notfull_next)
				       );

   assign issueptr = ~notfull ? allocptr :
		     ((b1 == 0) && (e1 == ENTNUM-1)) ? (e0+1) : 
		     b1;
   
   assign issuevalid = readyvec[issueptr] & ~prmiss & ~exunit_busynext;

   assign allocatable = (reqnum == 2'h0) ? 1'b1 :
			(reqnum == 2'h1) ? ((~busyvec[allocptr] ? 1'b1 : 1'b0)) :
			((~busyvec[allocptr] && ~busyvec[allocptr2]) ? 1'b1 : 1'b0);
   
   always @ (posedge clk) begin
      if (reset) begin
	 allocptr <= 0;
      end else if (prmiss) begin
	 allocptr <= ~notfull_next ? allocptr :
		     (((nb1 == 0) && (ne1 == ENTNUM-1)) ? nb0 : (ne1+1));
      end else if (~stall_DP && ~kill_DP) begin
	 allocptr <= allocptr + reqnum;
      end
   end
endmodule // alloc_issue_ino

//`default_nettype wire
`include "alu_ops.vh"
`include "rv32_opcodes.vh"

`default_nettype none
  
module alu(
           input wire [`ALU_OP_WIDTH-1:0] op,
           input wire [`XPR_LEN-1:0] 	  in1,
           input wire [`XPR_LEN-1:0] 	  in2,
           output reg [`XPR_LEN-1:0] 	  out
           );

   wire [`SHAMT_WIDTH-1:0] 	     shamt;

   assign shamt = in2[`SHAMT_WIDTH-1:0];

   always @(*) begin
      case (op)
        `ALU_OP_ADD : out = in1 + in2;
        `ALU_OP_SLL : out = in1 << shamt;
        `ALU_OP_XOR : out = in1 ^ in2;
        `ALU_OP_OR : out = in1 | in2;
        `ALU_OP_AND : out = in1 & in2;
        `ALU_OP_SRL : out = in1 >> shamt;
        `ALU_OP_SEQ : out = {31'b0, in1 == in2};
        `ALU_OP_SNE : out = {31'b0, in1 != in2};
        `ALU_OP_SUB : out = in1 - in2;
        `ALU_OP_SRA : out = $signed(in1) >>> shamt;
        `ALU_OP_SLT : out = {31'b0, $signed(in1) < $signed(in2)};
        `ALU_OP_SGE : out = {31'b0, $signed(in1) >= $signed(in2)};
        `ALU_OP_SLTU : out = {31'b0, in1 < in2};
        `ALU_OP_SGEU : out = {31'b0, in1 >= in2};
        default : out = 0;
      endcase // case op
   end


endmodule // alu

`default_nettype wire
`include "constants.vh"
`default_nettype none
module arf
  (
   input wire 			 clk,
   input wire 			 reset,
   input wire [`REG_SEL-1:0] 	 rs1_1, //DP from here
   input wire [`REG_SEL-1:0] 	 rs2_1,
   input wire [`REG_SEL-1:0] 	 rs1_2,
   input wire [`REG_SEL-1:0] 	 rs2_2,
   output wire [`DATA_LEN-1:0] 	 rs1_1data,
   output wire [`DATA_LEN-1:0] 	 rs2_1data,
   output wire [`DATA_LEN-1:0] 	 rs1_2data,
   output wire [`DATA_LEN-1:0] 	 rs2_2data, //DP end 
   input wire [`REG_SEL-1:0] 	 wreg1, //com_dst1
   input wire [`REG_SEL-1:0] 	 wreg2, //com_dst2
   input wire [`DATA_LEN-1:0] 	 wdata1, //com_data1
   input wire [`DATA_LEN-1:0] 	 wdata2, //com_data2
   input wire 			 we1, //com_en1
   input wire 			 we2, //com_en2
   input wire [`RRF_SEL-1:0] 	 wrrfent1, //comtag1
   input wire [`RRF_SEL-1:0] 	 wrrfent2, //comtag2
   output wire [`RRF_SEL-1:0] 	 rs1_1tag, // DP from here
   output wire [`RRF_SEL-1:0] 	 rs2_1tag,
   output wire [`RRF_SEL-1:0] 	 rs1_2tag,
   output wire [`RRF_SEL-1:0] 	 rs2_2tag,
   input wire [`REG_SEL-1:0] 	 tagbusy1_addr,
   input wire [`REG_SEL-1:0] 	 tagbusy2_addr,
   input wire 			 tagbusy1_we,
   input wire 			 tagbusy2_we,
   input wire [`RRF_SEL-1:0] 	 settag1,
   input wire [`RRF_SEL-1:0] 	 settag2,
   input wire [`SPECTAG_LEN-1:0] tagbusy1_spectag,
   input wire [`SPECTAG_LEN-1:0] tagbusy2_spectag,
   output wire 			 rs1_1busy,
   output wire 			 rs2_1busy,
   output wire 			 rs1_2busy,
   output wire 			 rs2_2busy,
   input wire 			 prmiss,
   input wire 			 prsuccess,
   input wire [`SPECTAG_LEN-1:0] prtag,
   input wire [`SPECTAG_LEN-1:0] mpft_valid1,
   input wire [`SPECTAG_LEN-1:0] mpft_valid2
   );

   // Set priority on instruction2 WriteBack
   // wrrfent = comtag
   wire [`RRF_SEL-1:0] 		 comreg1_tag;
   wire [`RRF_SEL-1:0] 		 comreg2_tag;
   wire 			 clearbusy1 = we1;
   wire 			 clearbusy2 = we2;

   wire 			 we1_0reg = we1 && 
				 (wreg1 != `REG_SEL'b0);
   
   wire 			 we2_0reg = we2 && 
				 (wreg2 != `REG_SEL'b0);
   
   wire 			 we1_prior2 = ((wreg1 == wreg2) &&
					       we1_0reg && we2_0reg) ? 
				 1'b0 : we1_0reg;
   
   // Set priority on instruction2 WriteBack
   // we when wrrfent1 == comreg1_tag
   ram_sync_nolatch_4r2w
     #(`REG_SEL, `DATA_LEN, `REG_NUM)
   regfile(
	   .clk(clk),
	   .raddr1(rs1_1),
	   .raddr2(rs2_1),
	   .raddr3(rs1_2),
	   .raddr4(rs2_2),
	   .rdata1(rs1_1data),
	   .rdata2(rs2_1data),
	   .rdata3(rs1_2data),
	   .rdata4(rs2_2data),
	   .waddr1(wreg1),
	   .waddr2(wreg2),
	   .wdata1(wdata1),
	   .wdata2(wdata2),
	   //	   .we1(we1_prior2),
	   .we1(we1_0reg),
	   .we2(we2_0reg)
	   );

   
   renaming_table rt(
		     .clk(clk),
		     .reset(reset),
		     .rs1_1(rs1_1),
		     .rs2_1(rs2_1),
		     .rs1_2(rs1_2),
		     .rs2_2(rs2_2),
		     .comreg1(wreg1),
		     .comreg2(wreg2),
		     .rs1_1tag(rs1_1tag),
		     .rs2_1tag(rs2_1tag),
		     .rs1_2tag(rs1_2tag),
		     .rs2_2tag(rs2_2tag),
		     .rs1_1busy(rs1_1busy),
		     .rs2_1busy(rs2_1busy),
		     .rs1_2busy(rs1_2busy),
		     .rs2_2busy(rs2_2busy),
		     .settagbusy1_addr(tagbusy1_addr),
		     .settagbusy2_addr(tagbusy2_addr),
		     .settagbusy1(tagbusy1_we),
		     .settagbusy2(tagbusy2_we),
		     .settag1(settag1),
		     .settag2(settag2),
		     .setbusy1_spectag(tagbusy1_spectag),
		     .setbusy2_spectag(tagbusy2_spectag),
		     .clearbusy1(clearbusy1),
		     .clearbusy2(clearbusy2),
		     .wrrfent1(wrrfent1),
		     .wrrfent2(wrrfent2),
		     .prmiss(prmiss),
		     .prsuccess(prsuccess),
		     .prtag(prtag),
		     .mpft_valid1(mpft_valid1),
		     .mpft_valid2(mpft_valid2)
		     );
   

endmodule // arf

// Set priority on instruction2 WriteBack
/*
 clear busy when comtag = rt_tag[comreg]
 */

module select_vector(
		     input wire [`SPECTAG_LEN-1:0] spectag,
		     input wire [`REG_NUM-1:0] 	   dat0,
		     input wire [`REG_NUM-1:0] 	   dat1,
		     input wire [`REG_NUM-1:0] 	   dat2,
		     input wire [`REG_NUM-1:0] 	   dat3,
		     input wire [`REG_NUM-1:0] 	   dat4,
		     output reg [`REG_NUM-1:0] 	   out
		     );

   always @ (*) begin
      out = 0;
      case (spectag)
	5'b00001 : out = dat1;
	5'b00010 : out = dat2;
	5'b00100 : out = dat3;
	5'b01000 : out = dat4;
	5'b10000 : out = dat0;
	default : out = 0;
      endcase // case (spectag) 
   end
endmodule // select_vector

module renaming_table
  (
   input wire 			 clk,
   input wire 			 reset,
   input wire [`REG_SEL-1:0] 	 rs1_1,
   input wire [`REG_SEL-1:0] 	 rs2_1,
   input wire [`REG_SEL-1:0] 	 rs1_2,
   input wire [`REG_SEL-1:0] 	 rs2_2,
   input wire [`REG_SEL-1:0] 	 comreg1, //clearbusy1addr
   input wire [`REG_SEL-1:0] 	 comreg2, //clearbusy2addr
   input wire 			 clearbusy1, //calc on arf
   input wire 			 clearbusy2,
   input wire [`RRF_SEL-1:0] 	 wrrfent1,
   input wire [`RRF_SEL-1:0] 	 wrrfent2, 
   output wire [`RRF_SEL-1:0] 	 rs1_1tag,
   output wire [`RRF_SEL-1:0] 	 rs2_1tag,
   output wire [`RRF_SEL-1:0] 	 rs1_2tag,
   output wire [`RRF_SEL-1:0] 	 rs2_2tag,
   output wire 			 rs1_1busy,
   output wire 			 rs2_1busy,
   output wire 			 rs1_2busy,
   output wire 			 rs2_2busy,
   input wire [`REG_SEL-1:0] 	 settagbusy1_addr,
   input wire [`REG_SEL-1:0] 	 settagbusy2_addr,
   input wire 			 settagbusy1,
   input wire 			 settagbusy2,
   input wire [`RRF_SEL-1:0] 	 settag1,
   input wire [`RRF_SEL-1:0] 	 settag2,
   input wire [`SPECTAG_LEN-1:0] setbusy1_spectag,
   input wire [`SPECTAG_LEN-1:0] setbusy2_spectag,

   input wire 			 prmiss,
   input wire 			 prsuccess,
   input wire [`SPECTAG_LEN-1:0] prtag,
   input wire [`SPECTAG_LEN-1:0] mpft_valid1,
   input wire [`SPECTAG_LEN-1:0] mpft_valid2
   );
   
   reg [`REG_NUM-1:0] 		 busy_0;
   reg [`REG_NUM-1:0] 		 tag0_0;
   reg [`REG_NUM-1:0] 		 tag1_0;
   reg [`REG_NUM-1:0] 		 tag2_0;
   reg [`REG_NUM-1:0] 		 tag3_0;
   reg [`REG_NUM-1:0] 		 tag4_0;
   reg [`REG_NUM-1:0] 		 tag5_0;
   
   reg [`REG_NUM-1:0] 		 busy_1;
   reg [`REG_NUM-1:0] 		 tag0_1;
   reg [`REG_NUM-1:0] 		 tag1_1;
   reg [`REG_NUM-1:0] 		 tag2_1;
   reg [`REG_NUM-1:0] 		 tag3_1;
   reg [`REG_NUM-1:0] 		 tag4_1;
   reg [`REG_NUM-1:0] 		 tag5_1;
   
   reg [`REG_NUM-1:0] 		 busy_2;
   reg [`REG_NUM-1:0] 		 tag0_2;
   reg [`REG_NUM-1:0] 		 tag1_2;
   reg [`REG_NUM-1:0] 		 tag2_2;
   reg [`REG_NUM-1:0] 		 tag3_2;
   reg [`REG_NUM-1:0] 		 tag4_2;
   reg [`REG_NUM-1:0] 		 tag5_2;
   
   reg [`REG_NUM-1:0] 		 busy_3;
   reg [`REG_NUM-1:0] 		 tag0_3;
   reg [`REG_NUM-1:0] 		 tag1_3;
   reg [`REG_NUM-1:0] 		 tag2_3;
   reg [`REG_NUM-1:0] 		 tag3_3;
   reg [`REG_NUM-1:0] 		 tag4_3;
   reg [`REG_NUM-1:0] 		 tag5_3;
   
   reg [`REG_NUM-1:0] 		 busy_4;
   reg [`REG_NUM-1:0] 		 tag0_4;
   reg [`REG_NUM-1:0] 		 tag1_4;
   reg [`REG_NUM-1:0] 		 tag2_4;
   reg [`REG_NUM-1:0] 		 tag3_4;
   reg [`REG_NUM-1:0] 		 tag4_4;
   reg [`REG_NUM-1:0] 		 tag5_4;
   
   reg [`REG_NUM-1:0] 		 busy_master;
   reg [`REG_NUM-1:0] 		 tag0_master;
   reg [`REG_NUM-1:0] 		 tag1_master;
   reg [`REG_NUM-1:0] 		 tag2_master;
   reg [`REG_NUM-1:0] 		 tag3_master;
   reg [`REG_NUM-1:0] 		 tag4_master;
   reg [`REG_NUM-1:0] 		 tag5_master;

   wire [`REG_NUM-1:0] 		 tag0;
   wire [`REG_NUM-1:0] 		 tag1;
   wire [`REG_NUM-1:0] 		 tag2;
   wire [`REG_NUM-1:0] 		 tag3;
   wire [`REG_NUM-1:0] 		 tag4;
   wire [`REG_NUM-1:0] 		 tag5;

   wire [`SPECTAG_LEN-1:0] 	 wesetvec1 = ~mpft_valid1;
   wire [`SPECTAG_LEN-1:0] 	 wesetvec2 = ~mpft_valid2;
   
   wire 			 settagbusy1_prior2 = settagbusy1 && settagbusy2 && 
				 (settagbusy1_addr == settagbusy2_addr) ? 1'b0 : settagbusy1;

   wire 			 clearbusy1_priorset = clearbusy1 && 
				 ~(
				   (settagbusy1 && (settagbusy1_addr == comreg1)) ||
				   (settagbusy2 && (settagbusy2_addr == comreg1))
				   );
   
   wire 			 clearbusy2_priorset = clearbusy2 &&
				 ~(
				   (settagbusy1 && (settagbusy1_addr == comreg2)) ||
				   (settagbusy2 && (settagbusy2_addr == comreg2))
				   );

   wire 			 setbusy1_master = settagbusy1_prior2;
   
   wire 			 setbusy2_master = settagbusy2;

   wire 			 clearbusy1_master = clearbusy1 &&  
				 (wrrfent1 == {tag5_master[comreg1], tag4_master[comreg1],
					       tag3_master[comreg1], tag2_master[comreg1], 
					       tag1_master[comreg1], tag0_master[comreg1]}) &&
				 ~((setbusy1_master && (settagbusy1_addr == comreg1)) ||
				   (setbusy2_master && (settagbusy2_addr == comreg1)));

   wire 			 clearbusy2_master = clearbusy2 &&  
				 (wrrfent2 == {tag5_master[comreg2], tag4_master[comreg2], 
					       tag3_master[comreg2], tag2_master[comreg2], 
					       tag1_master[comreg2], tag0_master[comreg2]}) &&
				 ~((setbusy1_master && (settagbusy1_addr == comreg2)) ||
				   (setbusy2_master && (settagbusy2_addr == comreg2)));

   
   wire 			 setbusy1_0 = settagbusy1_prior2 && wesetvec1[0];
   
   wire 			 setbusy2_0 = settagbusy2 && wesetvec2[0];

   wire 			 clearbusy1_0 = clearbusy1 &&  
				 (wrrfent1 == 
				  {tag5_0[comreg1], tag4_0[comreg1], tag3_0[comreg1],
				   tag2_0[comreg1], tag1_0[comreg1], tag0_0[comreg1]}) &&
				 ~((setbusy1_0 && (settagbusy1_addr == comreg1)) ||
				   (setbusy2_0 && (settagbusy2_addr == comreg1)));

   wire 			 clearbusy2_0 = clearbusy2 &&  
				 (wrrfent2 == 
				  {tag5_0[comreg2], tag4_0[comreg2], tag3_0[comreg2],
				   tag2_0[comreg2], tag1_0[comreg2], tag0_0[comreg2]}) &&
				 ~((setbusy1_0 && (settagbusy1_addr == comreg2)) ||
				   (setbusy2_0 && (settagbusy2_addr == comreg2)));

   wire 			 setbusy1_1 = settagbusy1_prior2 && wesetvec1[1];
   
   wire 			 setbusy2_1 = settagbusy2 && wesetvec2[1];

   wire 			 clearbusy1_1 = clearbusy1 &&  
				 (wrrfent1 == 
				  {tag5_1[comreg1], tag4_1[comreg1], tag3_1[comreg1],
				   tag2_1[comreg1], tag1_1[comreg1], tag0_1[comreg1]}) &&
				 ~((setbusy1_1 && (settagbusy1_addr == comreg1)) ||
				   (setbusy2_1 && (settagbusy2_addr == comreg1)));

   wire 			 clearbusy2_1 = clearbusy2 &&  
				 (wrrfent2 == 
				  {tag5_1[comreg2], tag4_1[comreg2], tag3_1[comreg2],
				   tag2_1[comreg2], tag1_1[comreg2], tag0_1[comreg2]}) &&
				 ~((setbusy1_1 && (settagbusy1_addr == comreg2)) ||
				   (setbusy2_1 && (settagbusy2_addr == comreg2)));

   wire 			 setbusy1_2 = settagbusy1_prior2 && wesetvec1[2];
   
   wire 			 setbusy2_2 = settagbusy2 && wesetvec2[2];

   wire 			 clearbusy1_2 = clearbusy1 &&  
				 (wrrfent1 == 
				  {tag5_2[comreg1], tag4_2[comreg1], tag3_2[comreg1],
				   tag2_2[comreg1], tag1_2[comreg1], tag0_2[comreg1]}) &&
				 ~((setbusy1_2 && (settagbusy1_addr == comreg1)) ||
				   (setbusy2_2 && (settagbusy2_addr == comreg1)));

   wire 			 clearbusy2_2 = clearbusy2 &&  
				 (wrrfent2 == 
				  {tag5_2[comreg2], tag4_2[comreg2], tag3_2[comreg2],
				   tag2_2[comreg2], tag1_2[comreg2], tag0_2[comreg2]}) &&
				 ~((setbusy1_2 && (settagbusy1_addr == comreg2)) ||
				   (setbusy2_2 && (settagbusy2_addr == comreg2)));

   wire 			 setbusy1_3 = settagbusy1_prior2 && wesetvec1[3];
   
   wire 			 setbusy2_3 = settagbusy2 && wesetvec2[3];

   wire 			 clearbusy1_3 = clearbusy1 &&  
				 (wrrfent1 == 
				  {tag5_3[comreg1], tag4_3[comreg1], tag3_3[comreg1],
				   tag2_3[comreg1], tag1_3[comreg1], tag0_3[comreg1]}) &&
				 ~((setbusy1_3 && (settagbusy1_addr == comreg1)) ||
				   (setbusy2_3 && (settagbusy2_addr == comreg1)));

   wire 			 clearbusy2_3 = clearbusy2 &&  
				 (wrrfent2 == 
				  {tag5_3[comreg2], tag4_3[comreg2], tag3_3[comreg2],
				   tag2_3[comreg2], tag1_3[comreg2], tag0_3[comreg2]}) &&
				 ~((setbusy1_3 && (settagbusy1_addr == comreg2)) ||
				   (setbusy2_3 && (settagbusy2_addr == comreg2)));

   wire 			 setbusy1_4 = settagbusy1_prior2 && wesetvec1[4];
   
   wire 			 setbusy2_4 = settagbusy2 && wesetvec2[4];

   wire 			 clearbusy1_4 = clearbusy1 &&  
				 (wrrfent1 == 
				  {tag5_4[comreg1], tag4_4[comreg1], tag3_4[comreg1],
				   tag2_4[comreg1], tag1_4[comreg1], tag0_4[comreg1]}) &&
				 ~((setbusy1_4 && (settagbusy1_addr == comreg1)) ||
				   (setbusy2_4 && (settagbusy2_addr == comreg1)));

   wire 			 clearbusy2_4 = clearbusy2 &&  
				 (wrrfent2 == 
				  {tag5_4[comreg2], tag4_4[comreg2], tag3_4[comreg2],
				   tag2_4[comreg2], tag1_4[comreg2], tag0_4[comreg2]}) &&
				 ~((setbusy1_4 && (settagbusy1_addr == comreg2)) ||
				   (setbusy2_4 && (settagbusy2_addr == comreg2)));

   wire [`REG_NUM-1:0] 		 next_bsymas = 
				 (busy_master &
				  ((clearbusy1_master) ? 
				   ~(`REG_NUM'b1 << comreg1) : 
				   ~(`REG_NUM'b0)) &
				  ((clearbusy2_master) ? 
				   ~(`REG_NUM'b1 << comreg2) : 
				   ~(`REG_NUM'b0))
				  );

   wire [`REG_NUM-1:0] 		 next_bsyand_0 =
				 ((clearbusy1_0) ? 
				  ~(`REG_NUM'b1 << comreg1) : 
				  ~(`REG_NUM'b0)) &
				 ((clearbusy2_0) ? 
				  ~(`REG_NUM'b1 << comreg2) : 
				  ~(`REG_NUM'b0));

   wire [`REG_NUM-1:0] 		 next_bsyand_1 =
				 ((clearbusy1_1) ? 
				  ~(`REG_NUM'b1 << comreg1) : 
				  ~(`REG_NUM'b0)) &
				 ((clearbusy2_1) ? 
				  ~(`REG_NUM'b1 << comreg2) : 
				  ~(`REG_NUM'b0));

   wire [`REG_NUM-1:0] 		 next_bsyand_2 =
				 ((clearbusy1_2) ? 
				  ~(`REG_NUM'b1 << comreg1) : 
				  ~(`REG_NUM'b0)) &
				 ((clearbusy2_2) ? 
				  ~(`REG_NUM'b1 << comreg2) : 
				  ~(`REG_NUM'b0));

   wire [`REG_NUM-1:0] 		 next_bsyand_3 =
				 ((clearbusy1_3) ? 
				  ~(`REG_NUM'b1 << comreg1) : 
				  ~(`REG_NUM'b0)) &
				 ((clearbusy2_3) ? 
				  ~(`REG_NUM'b1 << comreg2) : 
				  ~(`REG_NUM'b0));

   wire [`REG_NUM-1:0] 		 next_bsyand_4 =
				 ((clearbusy1_4) ? 
				  ~(`REG_NUM'b1 << comreg1) : 
				  ~(`REG_NUM'b0)) &
				 ((clearbusy2_4) ? 
				  ~(`REG_NUM'b1 << comreg2) : 
				  ~(`REG_NUM'b0));
   
   
   assign rs1_1busy = busy_master[rs1_1];
   assign rs2_1busy = busy_master[rs2_1];
   assign rs1_2busy = busy_master[rs1_2];
   assign rs2_2busy = busy_master[rs2_2];

   assign rs1_1tag = {tag5_master[rs1_1], tag4_master[rs1_1], tag3_master[rs1_1],
		      tag2_master[rs1_1], tag1_master[rs1_1], tag0_master[rs1_1]};
   assign rs2_1tag = {tag5_master[rs2_1], tag4_master[rs2_1], tag3_master[rs2_1],
		      tag2_master[rs2_1], tag1_master[rs2_1], tag0_master[rs2_1]};
   assign rs1_2tag = {tag5_master[rs1_2], tag4_master[rs1_2], tag3_master[rs1_2],
		      tag2_master[rs1_2], tag1_master[rs1_2], tag0_master[rs1_2]};
   assign rs2_2tag = {tag5_master[rs2_2], tag4_master[rs2_2], tag3_master[rs2_2],
		      tag2_master[rs2_2], tag1_master[rs2_2], tag0_master[rs2_2]};


   
   always @ (posedge clk) begin
      if (reset) begin
	 busy_0 <= 0;
	 busy_1 <= 0;
	 busy_2 <= 0;
	 busy_3 <= 0;
	 busy_4 <= 0;
	 busy_master <= 0;
      end else begin
	 if (prsuccess) begin
	    busy_master <= next_bsymas;
	    busy_1 <= (prtag == 5'b00010) ? next_bsymas : (next_bsyand_1 & busy_1);
	    busy_2 <= (prtag == 5'b00100) ? next_bsymas : (next_bsyand_2 & busy_2);
	    busy_3 <= (prtag == 5'b01000) ? next_bsymas : (next_bsyand_3 & busy_3);
	    busy_4 <= (prtag == 5'b10000) ? next_bsymas : (next_bsyand_4 & busy_4);
	    busy_0 <= (prtag == 5'b00001) ? next_bsymas : (next_bsyand_0 & busy_0);	    
	 end else if (prmiss) begin // if (prsuccess)
	    if (prtag == 5'b00010) begin
	       busy_0 <= busy_1;
	       busy_1 <= busy_1;
	       busy_2 <= busy_1;
	       busy_3 <= busy_1;
	       busy_4 <= busy_1;
	       busy_master <= busy_1;
	    end else if (prtag == 5'b00100) begin
	       busy_0 <= busy_2;
	       busy_1 <= busy_2;
	       busy_2 <= busy_2;
	       busy_3 <= busy_2;
	       busy_4 <= busy_2;
	       busy_master <= busy_2;
	    end else if (prtag == 5'b01000) begin
	       busy_0 <= busy_3;
	       busy_1 <= busy_3;
	       busy_2 <= busy_3;
	       busy_3 <= busy_3;
	       busy_4 <= busy_3;
	       busy_master <= busy_3;
	    end else if (prtag == 5'b10000) begin
	       busy_0 <= busy_4;
	       busy_1 <= busy_4;
	       busy_2 <= busy_4;
	       busy_3 <= busy_4;
	       busy_4 <= busy_4;
	       busy_master <= busy_4;
	    end else if (prtag == 5'b00001) begin
	       busy_0 <= busy_0;
	       busy_1 <= busy_0;
	       busy_2 <= busy_0;
	       busy_3 <= busy_0;
	       busy_4 <= busy_0;
	       busy_master <= busy_0;
	    end
	 end else begin // if (prmiss)
	    /*
	     if (setbusy1_j)
	     busy_j[settagbusy1_addr] <= 1'b1;
	     if (setbusy2_j)
	     busy_j[settagbusy2_addr] <= 1'b1;
	     if (clearbusy1_j)
	     busy_j[comreg1] <= 1'b0;
	     if (clearbusy2_j)
	     busy_j[comreg2] <= 1'b0;
	     */
	    if (setbusy1_master)
	      busy_master[settagbusy1_addr] <= 1'b1;
	    if (setbusy2_master)
	      busy_master[settagbusy2_addr] <= 1'b1;
	    if (clearbusy1_master)
	      busy_master[comreg1] <= 1'b0;
	    if (clearbusy2_master)
	      busy_master[comreg2] <= 1'b0;

	    if (setbusy1_0)
	      busy_0[settagbusy1_addr] <= 1'b1;
	    if (setbusy2_0)
	      busy_0[settagbusy2_addr] <= 1'b1;
	    if (clearbusy1_0)
	      busy_0[comreg1] <= 1'b0;
	    if (clearbusy2_0)
	      busy_0[comreg2] <= 1'b0;

	    if (setbusy1_1)
	      busy_1[settagbusy1_addr] <= 1'b1;
	    if (setbusy2_1)
	      busy_1[settagbusy2_addr] <= 1'b1;
	    if (clearbusy1_1)
	      busy_1[comreg1] <= 1'b0;
	    if (clearbusy2_1)
	      busy_1[comreg2] <= 1'b0;

	    if (setbusy1_2)
	      busy_2[settagbusy1_addr] <= 1'b1;
	    if (setbusy2_2)
	      busy_2[settagbusy2_addr] <= 1'b1;
	    if (clearbusy1_2)
	      busy_2[comreg1] <= 1'b0;
	    if (clearbusy2_2)
	      busy_2[comreg2] <= 1'b0;

	    if (setbusy1_3)
	      busy_3[settagbusy1_addr] <= 1'b1;
	    if (setbusy2_3)
	      busy_3[settagbusy2_addr] <= 1'b1;
	    if (clearbusy1_3)
	      busy_3[comreg1] <= 1'b0;
	    if (clearbusy2_3)
	      busy_3[comreg2] <= 1'b0;

	    if (setbusy1_4)
	      busy_4[settagbusy1_addr] <= 1'b1;
	    if (setbusy2_4)
	      busy_4[settagbusy2_addr] <= 1'b1;
	    if (clearbusy1_4)
	      busy_4[comreg1] <= 1'b0;
	    if (clearbusy2_4)
	      busy_4[comreg2] <= 1'b0;

	 end // else: !if(prmiss)
      end // else: !if(reset)
   end // always @ (posedge clk)

   always @ (posedge clk) begin
      if (reset) begin
	 tag0_0 <= 0;
	 tag1_0 <= 0;
	 tag2_0 <= 0;
	 tag3_0 <= 0;
	 tag4_0 <= 0;
	 tag5_0 <= 0;
	 tag0_1 <= 0;
	 tag1_1 <= 0;
	 tag2_1 <= 0;
	 tag3_1 <= 0;
	 tag4_1 <= 0;
	 tag5_1 <= 0;
	 tag0_2 <= 0;
	 tag1_2 <= 0;
	 tag2_2 <= 0;
	 tag3_2 <= 0;
	 tag4_2 <= 0;
	 tag5_2 <= 0;
	 tag0_3 <= 0;
	 tag1_3 <= 0;
	 tag2_3 <= 0;
	 tag3_3 <= 0;
	 tag4_3 <= 0;
	 tag5_3 <= 0;
	 tag0_4 <= 0;
	 tag1_4 <= 0;
	 tag2_4 <= 0;
	 tag3_4 <= 0;
	 tag4_4 <= 0;
	 tag5_4 <= 0;
	 tag0_master <= 0;
	 tag1_master <= 0;
	 tag2_master <= 0;
	 tag3_master <= 0;
	 tag4_master <= 0;
	 tag5_master <= 0;
      end else if (prsuccess) begin
	 tag0_master <= tag0_master;
	 tag1_master <= tag1_master;
	 tag2_master <= tag2_master;
	 tag3_master <= tag3_master;
	 tag4_master <= tag4_master;	 
	 tag5_master <= tag5_master;
	 
	 if (prtag == 5'b00010) begin
	    tag0_1 <= tag0_master;
	    tag1_1 <= tag1_master;
	    tag2_1 <= tag2_master;
	    tag3_1 <= tag3_master;
	    tag4_1 <= tag4_master;
	    tag5_1 <= tag5_master;
	 end else if (prtag == 5'b00100) begin
	    tag0_2 <= tag0_master;
	    tag1_2 <= tag1_master;
	    tag2_2 <= tag2_master;
	    tag3_2 <= tag3_master;
	    tag4_2 <= tag4_master;
	    tag5_2 <= tag5_master;
	 end else if (prtag == 5'b01000) begin
	    tag0_3 <= tag0_master;
	    tag1_3 <= tag1_master;
	    tag2_3 <= tag2_master;
	    tag3_3 <= tag3_master;
	    tag4_3 <= tag4_master;
	    tag5_3 <= tag5_master;
	 end else if (prtag == 5'b10000) begin
	    tag0_4 <= tag0_master;
	    tag1_4 <= tag1_master;
	    tag2_4 <= tag2_master;
	    tag3_4 <= tag3_master;
	    tag4_4 <= tag4_master;
	    tag5_4 <= tag5_master;
	 end else if (prtag == 5'b00001) begin
	    tag0_0 <= tag0_master;
	    tag1_0 <= tag1_master;
	    tag2_0 <= tag2_master;
	    tag3_0 <= tag3_master;
	    tag4_0 <= tag4_master;
	    tag5_0 <= tag5_master;
	 end
      end else if (prmiss) begin // if (prsuccess)
	 if (prtag == 5'b00010) begin
	    tag0_0 <= tag0_1;
	    tag1_0 <= tag1_1;
	    tag2_0 <= tag2_1;
	    tag3_0 <= tag3_1;
	    tag4_0 <= tag4_1;
	    tag5_0 <= tag5_1;
	    tag0_1 <= tag0_1;
	    tag1_1 <= tag1_1;
	    tag2_1 <= tag2_1;
	    tag3_1 <= tag3_1;
	    tag4_1 <= tag4_1;
	    tag5_1 <= tag5_1;
	    tag0_2 <= tag0_1;
	    tag1_2 <= tag1_1;
	    tag2_2 <= tag2_1;
	    tag3_2 <= tag3_1;
	    tag4_2 <= tag4_1;
	    tag5_2 <= tag5_1;
	    tag0_3 <= tag0_1;
	    tag1_3 <= tag1_1;
	    tag2_3 <= tag2_1;
	    tag3_3 <= tag3_1;
	    tag4_3 <= tag4_1;
	    tag5_3 <= tag5_1;
	    tag0_4 <= tag0_1;
	    tag1_4 <= tag1_1;
	    tag2_4 <= tag2_1;
	    tag3_4 <= tag3_1;
	    tag4_4 <= tag4_1;
	    tag5_4 <= tag5_1;
	    tag0_master <= tag0_1;
	    tag1_master <= tag1_1;
	    tag2_master <= tag2_1;
	    tag3_master <= tag3_1;
	    tag4_master <= tag4_1;
	    tag5_master <= tag5_1;
	 end else if (prtag == 5'b00100) begin
	    tag0_0 <= tag0_2;
	    tag1_0 <= tag1_2;
	    tag2_0 <= tag2_2;
	    tag3_0 <= tag3_2;
	    tag4_0 <= tag4_2;
	    tag5_0 <= tag5_2;
	    tag0_1 <= tag0_2;
	    tag1_1 <= tag1_2;
	    tag2_1 <= tag2_2;
	    tag3_1 <= tag3_2;
	    tag4_1 <= tag4_2;
	    tag5_1 <= tag5_2;
	    tag0_2 <= tag0_2;
	    tag1_2 <= tag1_2;
	    tag2_2 <= tag2_2;
	    tag3_2 <= tag3_2;
	    tag4_2 <= tag4_2;
	    tag5_2 <= tag5_2;
	    tag0_3 <= tag0_2;
	    tag1_3 <= tag1_2;
	    tag2_3 <= tag2_2;
	    tag3_3 <= tag3_2;
	    tag4_3 <= tag4_2;
	    tag5_3 <= tag5_2;
	    tag0_4 <= tag0_2;
	    tag1_4 <= tag1_2;
	    tag2_4 <= tag2_2;
	    tag3_4 <= tag3_2;
	    tag4_4 <= tag4_2;
	    tag5_4 <= tag5_2;
	    tag0_master <= tag0_2;
	    tag1_master <= tag1_2;
	    tag2_master <= tag2_2;
	    tag3_master <= tag3_2;
	    tag4_master <= tag4_2;
	    tag5_master <= tag5_2;
	 end else if (prtag == 5'b01000) begin
	    tag0_0 <= tag0_3;
	    tag1_0 <= tag1_3;
	    tag2_0 <= tag2_3;
	    tag3_0 <= tag3_3;
	    tag4_0 <= tag4_3;
	    tag5_0 <= tag5_3;
	    tag0_1 <= tag0_3;
	    tag1_1 <= tag1_3;
	    tag2_1 <= tag2_3;
	    tag3_1 <= tag3_3;
	    tag4_1 <= tag4_3;
	    tag5_1 <= tag5_3;
	    tag0_2 <= tag0_3;
	    tag1_2 <= tag1_3;
	    tag2_2 <= tag2_3;
	    tag3_2 <= tag3_3;
	    tag4_2 <= tag4_3;
	    tag5_2 <= tag5_3;
	    tag0_3 <= tag0_3;
	    tag1_3 <= tag1_3;
	    tag2_3 <= tag2_3;
	    tag3_3 <= tag3_3;
	    tag4_3 <= tag4_3;
	    tag5_3 <= tag5_3;
	    tag0_4 <= tag0_3;
	    tag1_4 <= tag1_3;
	    tag2_4 <= tag2_3;
	    tag3_4 <= tag3_3;
	    tag4_4 <= tag4_3;
	    tag5_4 <= tag5_3;
	    tag0_master <= tag0_3;
	    tag1_master <= tag1_3;
	    tag2_master <= tag2_3;
	    tag3_master <= tag3_3;
	    tag4_master <= tag4_3;
	    tag5_master <= tag5_3;
	 end else if (prtag == 5'b10000) begin
	    tag0_0 <= tag0_4;
	    tag1_0 <= tag1_4;
	    tag2_0 <= tag2_4;
	    tag3_0 <= tag3_4;
	    tag4_0 <= tag4_4;
	    tag5_0 <= tag5_4;
	    tag0_1 <= tag0_4;
	    tag1_1 <= tag1_4;
	    tag2_1 <= tag2_4;
	    tag3_1 <= tag3_4;
	    tag4_1 <= tag4_4;
	    tag5_1 <= tag5_4;
	    tag0_2 <= tag0_4;
	    tag1_2 <= tag1_4;
	    tag2_2 <= tag2_4;
	    tag3_2 <= tag3_4;
	    tag4_2 <= tag4_4;
	    tag5_2 <= tag5_4;
	    tag0_3 <= tag0_4;
	    tag1_3 <= tag1_4;
	    tag2_3 <= tag2_4;
	    tag3_3 <= tag3_4;
	    tag4_3 <= tag4_4;
	    tag5_3 <= tag5_4;
	    tag0_4 <= tag0_4;
	    tag1_4 <= tag1_4;
	    tag2_4 <= tag2_4;
	    tag3_4 <= tag3_4;
	    tag4_4 <= tag4_4;
	    tag5_4 <= tag5_4;
	    tag0_master <= tag0_4;
	    tag1_master <= tag1_4;
	    tag2_master <= tag2_4;
	    tag3_master <= tag3_4;
	    tag4_master <= tag4_4;
	    tag5_master <= tag5_4;
	 end else if (prtag == 5'b00001) begin
	    tag0_0 <= tag0_0;
	    tag1_0 <= tag1_0;
	    tag2_0 <= tag2_0;
	    tag3_0 <= tag3_0;
	    tag4_0 <= tag4_0;
	    tag5_0 <= tag5_0;
	    tag0_1 <= tag0_0;
	    tag1_1 <= tag1_0;
	    tag2_1 <= tag2_0;
	    tag3_1 <= tag3_0;
	    tag4_1 <= tag4_0;
	    tag5_1 <= tag5_0;
	    tag0_2 <= tag0_0;
	    tag1_2 <= tag1_0;
	    tag2_2 <= tag2_0;
	    tag3_2 <= tag3_0;
	    tag4_2 <= tag4_0;
	    tag5_2 <= tag5_0;
	    tag0_3 <= tag0_0;
	    tag1_3 <= tag1_0;
	    tag2_3 <= tag2_0;
	    tag3_3 <= tag3_0;
	    tag4_3 <= tag4_0;
	    tag5_3 <= tag5_0;
	    tag0_4 <= tag0_0;
	    tag1_4 <= tag1_0;
	    tag2_4 <= tag2_0;
	    tag3_4 <= tag3_0;
	    tag4_4 <= tag4_0;
	    tag5_4 <= tag5_0;
	    tag0_master <= tag0_0;
	    tag1_master <= tag1_0;
	    tag2_master <= tag2_0;
	    tag3_master <= tag3_0;
	    tag4_master <= tag4_0;
	    tag5_master <= tag5_0;
	 end 
      end else begin // if (prmiss)
	 if (settagbusy1) begin
	    //TAG0
	    tag0_master[settagbusy1_addr] <= settagbusy1_prior2 ?
					     settag1[0] : tag0_master[settagbusy1_addr];
	    
	    tag0_0[settagbusy1_addr] <= (wesetvec1[0] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[0] : tag0_0[settagbusy1_addr];
	    tag0_1[settagbusy1_addr] <= (wesetvec1[1] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[0] : tag0_1[settagbusy1_addr];
	    tag0_2[settagbusy1_addr] <= (wesetvec1[2] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[0] : tag0_2[settagbusy1_addr];
	    tag0_3[settagbusy1_addr] <= (wesetvec1[3] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[0] : tag0_3[settagbusy1_addr];
	    tag0_4[settagbusy1_addr] <= (wesetvec1[4] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[0] : tag0_4[settagbusy1_addr];
	    //TAG1
	    tag1_master[settagbusy1_addr] <= settagbusy1_prior2 ?
					     settag1[1] : tag1_master[settagbusy1_addr];
	    
	    tag1_0[settagbusy1_addr] <= (wesetvec1[0] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[1] : tag1_0[settagbusy1_addr];
	    tag1_1[settagbusy1_addr] <= (wesetvec1[1] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[1] : tag1_1[settagbusy1_addr];
	    tag1_2[settagbusy1_addr] <= (wesetvec1[2] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[1] : tag1_2[settagbusy1_addr];
	    tag1_3[settagbusy1_addr] <= (wesetvec1[3] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[1] : tag1_3[settagbusy1_addr];
	    tag1_4[settagbusy1_addr] <= (wesetvec1[4] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[1] : tag1_4[settagbusy1_addr];
	    //TAG2
	    tag2_master[settagbusy1_addr] <= settagbusy1_prior2 ?
					     settag1[2] : tag2_master[settagbusy1_addr];
	    tag2_0[settagbusy1_addr] <= (wesetvec1[0] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[2] : tag2_0[settagbusy1_addr];
	    tag2_1[settagbusy1_addr] <= (wesetvec1[1] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[2] : tag2_1[settagbusy1_addr];
	    tag2_2[settagbusy1_addr] <= (wesetvec1[2] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[2] : tag2_2[settagbusy1_addr];
	    tag2_3[settagbusy1_addr] <= (wesetvec1[3] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[2] : tag2_3[settagbusy1_addr];
	    tag2_4[settagbusy1_addr] <= (wesetvec1[4] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[2] : tag2_4[settagbusy1_addr];
	    //TAG3
	    tag3_master[settagbusy1_addr] <= settagbusy1_prior2 ?
					     settag1[3] : tag3_master[settagbusy1_addr];
	    tag3_0[settagbusy1_addr] <= (wesetvec1[0] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[3] : tag3_0[settagbusy1_addr];
	    tag3_1[settagbusy1_addr] <= (wesetvec1[1] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[3] : tag3_1[settagbusy1_addr];
	    tag3_2[settagbusy1_addr] <= (wesetvec1[2] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[3] : tag3_2[settagbusy1_addr];
	    tag3_3[settagbusy1_addr] <= (wesetvec1[3] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[3] : tag3_3[settagbusy1_addr];
	    tag3_4[settagbusy1_addr] <= (wesetvec1[4] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[3] : tag3_4[settagbusy1_addr];
	    //TAG4
	    tag4_master[settagbusy1_addr] <= settagbusy1_prior2 ?
					     settag1[4] : tag4_master[settagbusy1_addr];
	    tag4_0[settagbusy1_addr] <= (wesetvec1[0] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[4] : tag4_0[settagbusy1_addr];
	    tag4_1[settagbusy1_addr] <= (wesetvec1[1] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[4] : tag4_1[settagbusy1_addr];
	    tag4_2[settagbusy1_addr] <= (wesetvec1[2] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[4] : tag4_2[settagbusy1_addr];
	    tag4_3[settagbusy1_addr] <= (wesetvec1[3] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[4] : tag4_3[settagbusy1_addr];
	    tag4_4[settagbusy1_addr] <= (wesetvec1[4] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[4] : tag4_4[settagbusy1_addr];
	    //TAG5
	    tag5_master[settagbusy1_addr] <= settagbusy1_prior2 ?
					     settag1[5] : tag5_master[settagbusy1_addr];
	    tag5_0[settagbusy1_addr] <= (wesetvec1[0] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[5] : tag5_0[settagbusy1_addr];
	    tag5_1[settagbusy1_addr] <= (wesetvec1[1] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[5] : tag5_1[settagbusy1_addr];
	    tag5_2[settagbusy1_addr] <= (wesetvec1[2] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[5] : tag5_2[settagbusy1_addr];
	    tag5_3[settagbusy1_addr] <= (wesetvec1[3] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[5] : tag5_3[settagbusy1_addr];
	    tag5_4[settagbusy1_addr] <= (wesetvec1[4] & 
					 (settagbusy1_prior2 | 
					  (setbusy1_spectag != setbusy2_spectag))) ?
					settag1[5] : tag5_4[settagbusy1_addr];
	    
	 end // if (setttagbusy1)
	 if (settagbusy2) begin
	    //TAG0
	    tag0_master[settagbusy2_addr] <= settag2[0];
	    
	    tag0_0[settagbusy2_addr] <= wesetvec2[0] ? 
					settag2[0] : tag0_0[settagbusy2_addr];
	    tag0_1[settagbusy2_addr] <= wesetvec2[1] ? 
					settag2[0] : tag0_1[settagbusy2_addr];
	    tag0_2[settagbusy2_addr] <= wesetvec2[2] ? 
					settag2[0] : tag0_2[settagbusy2_addr];
	    tag0_3[settagbusy2_addr] <= wesetvec2[3] ? 
					settag2[0] : tag0_3[settagbusy2_addr];
	    tag0_4[settagbusy2_addr] <= wesetvec2[4] ? 
					settag2[0] : tag0_4[settagbusy2_addr];
	    //TAG1
	    tag1_master[settagbusy2_addr] <= settag2[1];
	    
	    tag1_0[settagbusy2_addr] <= wesetvec2[0] ? 
					settag2[1] : tag1_0[settagbusy2_addr];
	    tag1_1[settagbusy2_addr] <= wesetvec2[1] ? 
					settag2[1] : tag1_1[settagbusy2_addr];
	    tag1_2[settagbusy2_addr] <= wesetvec2[2] ? 
					settag2[1] : tag1_2[settagbusy2_addr];
	    tag1_3[settagbusy2_addr] <= wesetvec2[3] ? 
					settag2[1] : tag1_3[settagbusy2_addr];
	    tag1_4[settagbusy2_addr] <= wesetvec2[4] ? 
					settag2[1] : tag1_4[settagbusy2_addr];
	    //TAG2
	    tag2_master[settagbusy2_addr] <= settag2[2];
	    tag2_0[settagbusy2_addr] <= wesetvec2[0] ? 
					settag2[2] : tag2_0[settagbusy2_addr];
	    tag2_1[settagbusy2_addr] <= wesetvec2[1] ? 
					settag2[2] : tag2_1[settagbusy2_addr];
	    tag2_2[settagbusy2_addr] <= wesetvec2[2] ? 
					settag2[2] : tag2_2[settagbusy2_addr];
	    tag2_3[settagbusy2_addr] <= wesetvec2[3] ? 
					settag2[2] : tag2_3[settagbusy2_addr];
	    tag2_4[settagbusy2_addr] <= wesetvec2[4] ? 
					settag2[2] : tag2_4[settagbusy2_addr];
	    //TAG3
	    tag3_master[settagbusy2_addr] <= settag2[3];
	    tag3_0[settagbusy2_addr] <= wesetvec2[0] ? 
					settag2[3] : tag3_0[settagbusy2_addr];
	    tag3_1[settagbusy2_addr] <= wesetvec2[1] ? 
					settag2[3] : tag3_1[settagbusy2_addr];
	    tag3_2[settagbusy2_addr] <= wesetvec2[2] ? 
					settag2[3] : tag3_2[settagbusy2_addr];
	    tag3_3[settagbusy2_addr] <= wesetvec2[3] ? 
					settag2[3] : tag3_3[settagbusy2_addr];
	    tag3_4[settagbusy2_addr] <= wesetvec2[4] ? 
					settag2[3] : tag3_4[settagbusy2_addr];
	    //TAG4
	    tag4_master[settagbusy2_addr] <= settag2[4];
	    tag4_0[settagbusy2_addr] <= wesetvec2[0] ? 
					settag2[4] : tag4_0[settagbusy2_addr];
	    tag4_1[settagbusy2_addr] <= wesetvec2[1] ? 
					settag2[4] : tag4_1[settagbusy2_addr];
	    tag4_2[settagbusy2_addr] <= wesetvec2[2] ? 
					settag2[4] : tag4_2[settagbusy2_addr];
	    tag4_3[settagbusy2_addr] <= wesetvec2[3] ? 
					settag2[4] : tag4_3[settagbusy2_addr];
	    tag4_4[settagbusy2_addr] <= wesetvec2[4] ? 
					settag2[4] : tag4_4[settagbusy2_addr];
	    //TAG5
	    tag5_master[settagbusy2_addr] <= settag2[5];
	    tag5_0[settagbusy2_addr] <= wesetvec2[0] ? 
					settag2[5] : tag5_0[settagbusy2_addr];
	    tag5_1[settagbusy2_addr] <= wesetvec2[1] ? 
					settag2[5] : tag5_1[settagbusy2_addr];
	    tag5_2[settagbusy2_addr] <= wesetvec2[2] ? 
					settag2[5] : tag5_2[settagbusy2_addr];
	    tag5_3[settagbusy2_addr] <= wesetvec2[3] ? 
					settag2[5] : tag5_3[settagbusy2_addr];
	    tag5_4[settagbusy2_addr] <= wesetvec2[4] ? 
					settag2[5] : tag5_4[settagbusy2_addr];
	 end
      end
   end
endmodule // renaming_table
`default_nettype wire
`include "constants.vh"
`include "rv32_opcodes.vh"
`default_nettype none
module brimm_gen
  (
   input wire [`INSN_LEN-1:0]  inst,
   output wire [`DATA_LEN-1:0] brimm
   );

   wire [`DATA_LEN-1:0]        br_offset = { {20{inst[31]}}, inst[7], 
					     inst[30:25], inst[11:8], 1'b0 };
   wire [`DATA_LEN-1:0]        jal_offset = { {12{inst[31]}}, inst[19:12], 
					      inst[20], inst[30:25], inst[24:21], 1'b0 };
   wire [`DATA_LEN-1:0]        jalr_offset = { {21{inst[31]}}, inst[30:21], 1'b0 };

   wire [6:0] 		       opcode = inst[6:0];
   
   assign brimm = (opcode == `RV32_BRANCH) ? br_offset :
		  (opcode == `RV32_JAL) ? jal_offset :
		  (opcode == `RV32_JALR) ? jalr_offset :
		  `DATA_LEN'b0;

endmodule // brimm_gen
`default_nettype wire  
`include "constants.vh"
`default_nettype none

//btb 基于两块ram实现，

module btb(
	   input wire 		       clk,
	   input wire 		       reset,
	   input wire [`ADDR_LEN-1:0]  pc,

	   output wire 		       hit,
	   output wire [`ADDR_LEN-1:0] jmpaddr,

	   input wire 		       we,
	   input wire [`ADDR_LEN-1:0]  jmpsrc,
	   input wire [`ADDR_LEN-1:0]  jmpdst,
	   input wire 		       invalid2
	   );

   wire [`ADDR_LEN-1:0] 	  tag_data;
   reg [`BTB_IDX_NUM-1:0] 	  valid;
   wire [`BTB_IDX_SEL-1:0] 	  waddr = jmpsrc[3+:`BTB_IDX_SEL];
   wire [`ADDR_LEN-1:0] 	  pc2 = pc+4;
   
   wire 			  hit1 = ((tag_data == pc) && valid[pc[3+:`BTB_IDX_SEL]]) ? 
				  1'b1 : 1'b0;
   //TODO: why consider invalid2?
   wire 			  hit2 = ((tag_data == pc2) && ~invalid2 
					  && valid[pc[3+:`BTB_IDX_SEL]]) ? 1'b1 : 1'b0;
   assign hit = hit1 | hit2;
	
   //TODO: 为什么打一拍更新valid?
   // we ==    assign combranch = (~prmiss & commit1 & isbranch[comptr]) |
	//	                            (~prmiss & commit2 & isbranch[comptr2]);
   //    其中  assign prmiss = busy & ~addrmatch;
   always @ (negedge clk) begin
      if (reset) begin
	      valid <= 0;
      end else begin
	   if (we) begin
	      valid[waddr] <= 1'b1;
	 end
      end
   end
   

   // BTB tag data( | )

   // branch instruction address, pc用于索引，读出tag_data用于比较
   // ram : 9 * 32 * 512
   ram_sync_1r1w #(`BTB_IDX_SEL, `ADDR_LEN, `BTB_IDX_NUM) bia
     (
      .clk(~clk),
      .raddr1(pc[3+:`BTB_IDX_SEL]),
      .rdata1(tag_data),
      .waddr(waddr),
//    .wdata(jmpsrc[31:3+`BTB_IDX_SEL]),
      .wdata(jmpsrc),
      .we(we)
      );

   // branch target address，pc用于索引，读出jmpaddr作为预测跳转的地址
   // ram : 9 * 32 * 512
   ram_sync_1r1w #(`BTB_IDX_SEL, `ADDR_LEN, `BTB_IDX_NUM) bta
     (
      .clk(~clk),
      .raddr1(pc[3+:`BTB_IDX_SEL]),
      .rdata1(jmpaddr),
      .waddr(waddr),
      .wdata(jmpdst),
      .we(we)
      );
        
endmodule // btb
`default_nettype wire
`include "constants.vh"
`include "rv32_opcodes.vh"
`include "alu_ops.vh"

`default_nettype none
module decoder(
	       input wire [31:0] 		  inst,
	       output reg [`IMM_TYPE_WIDTH-1:0]   imm_type,
	       output wire [`REG_SEL-1:0] 	  rs1,
	       output wire [`REG_SEL-1:0] 	  rs2,
	       output wire [`REG_SEL-1:0] 	  rd,
	       output reg [`SRC_A_SEL_WIDTH-1:0]  src_a_sel,
               output reg [`SRC_B_SEL_WIDTH-1:0]  src_b_sel,
	       output reg 			  wr_reg,
	       
	       output reg 			  uses_rs1,
	       output reg 			  uses_rs2,
	       output reg 			  illegal_instruction,
	       output reg [`ALU_OP_WIDTH-1:0] 	  alu_op,
	       output reg [`RS_ENT_SEL-1:0] 	  rs_ent,
//	       output reg 			  dmem_use,
//	       output reg 			  dmem_write,
	       output wire [2:0] 		  dmem_size,
	       output wire [`MEM_TYPE_WIDTH-1:0]  dmem_type, 
	       output reg [`MD_OP_WIDTH-1:0] 	  md_req_op,
	       output reg 			  md_req_in_1_signed,
	       output reg 			  md_req_in_2_signed,
	       output reg [`MD_OUT_SEL_WIDTH-1:0] md_req_out_sel

	       );

   wire [`ALU_OP_WIDTH-1:0] 			  srl_or_sra;
   wire [`ALU_OP_WIDTH-1:0] 			  add_or_sub;
   wire [`RS_ENT_SEL-1:0] 			  rs_ent_md;
   
   wire [6:0] 		    opcode = inst[6:0];
   wire [6:0] 		    funct7 = inst[31:25];
   wire [11:0] 		    funct12 = inst[31:20];
   wire [2:0] 		    funct3 = inst[14:12];
// reg [`MD_OP_WIDTH-1:0]   md_req_op;
   reg [`ALU_OP_WIDTH-1:0]  alu_op_arith;
   
   assign rd = inst[11:7];
   assign rs1 = inst[19:15];
   assign rs2 = inst[24:20];

   assign dmem_size = {1'b0,funct3[1:0]};
   assign dmem_type = funct3;
   
   always @ (*) begin
      imm_type = `IMM_I;
      src_a_sel = `SRC_A_RS1;
      src_b_sel = `SRC_B_IMM;
      wr_reg = 1'b0;
      uses_rs1 = 1'b1;
      uses_rs2 = 1'b0;
      illegal_instruction = 1'b0;
      //      dmem_use = 1'b0;
      //     dmem_write = 1'b0;
      rs_ent = `RS_ENT_ALU;
      alu_op = `ALU_OP_ADD;
      
      case (opcode)
	`RV32_LOAD : begin
//           dmem_use = 1'b1;
           wr_reg = 1'b1;
	   rs_ent = `RS_ENT_LDST;
//           wb_src_sel_DX = `WB_SRC_MEM;
        end
        `RV32_STORE : begin
           uses_rs2 = 1'b1;
           imm_type = `IMM_S;
//           dmem_use = 1'b1;
 //          dmem_write = 1'b1;
	   rs_ent = `RS_ENT_LDST;
        end
        `RV32_BRANCH : begin
           uses_rs2 = 1'b1;
           //branch_taken_unkilled = cmp_true;
           src_b_sel = `SRC_B_RS2;
           case (funct3)
             `RV32_FUNCT3_BEQ : alu_op = `ALU_OP_SEQ;
             `RV32_FUNCT3_BNE : alu_op = `ALU_OP_SNE;
             `RV32_FUNCT3_BLT : alu_op = `ALU_OP_SLT;
             `RV32_FUNCT3_BLTU : alu_op = `ALU_OP_SLTU;
             `RV32_FUNCT3_BGE : alu_op = `ALU_OP_SGE;
             `RV32_FUNCT3_BGEU : alu_op = `ALU_OP_SGEU;
             default : illegal_instruction = 1'b1;
           endcase // case (funct3)
	   rs_ent = `RS_ENT_BRANCH;
        end
        `RV32_JAL : begin
	   //           jal_unkilled = 1'b1;
           uses_rs1 = 1'b0;
           src_a_sel = `SRC_A_PC;
           src_b_sel = `SRC_B_FOUR;
           wr_reg = 1'b1;
	   rs_ent = `RS_ENT_JAL;
        end
        `RV32_JALR : begin
           illegal_instruction = (funct3 != 0);
	   //           jalr_unkilled = 1'b1;
           src_a_sel = `SRC_A_PC;
           src_b_sel = `SRC_B_FOUR;
           wr_reg = 1'b1;
	   rs_ent = `RS_ENT_JALR;
        end
	/*
        `RV32_MISC_MEM : begin
           case (funct3)
             `RV32_FUNCT3_FENCE : begin
                if ((inst[31:28] == 0) && (rs1 == 0) && (reg_to_wr_DX == 0))
                  ; // most fences are no-ops
                else
                  illegal_instruction = 1'b1;
             end
             `RV32_FUNCT3_FENCE_I : begin
                if ((inst[31:20] == 0) && (rs1 == 0) && (reg_to_wr_DX == 0))
                  fence_i = 1'b1;
                else
                  illegal_instruction = 1'b1;
             end
             default : illegal_instruction = 1'b1;
           endcase // case (funct3)
        end
	 */
        `RV32_OP_IMM : begin
           alu_op = alu_op_arith;
           wr_reg = 1'b1;
        end
        `RV32_OP  : begin
           uses_rs2 = 1'b1;
           src_b_sel = `SRC_B_RS2;
           alu_op = alu_op_arith;
           wr_reg = 1'b1;
           if (funct7 == `RV32_FUNCT7_MUL_DIV) begin
//              uses_md_unkilled = 1'b1;
	      rs_ent = rs_ent_md;
//              wb_src_sel_DX = `WB_SRC_MD;
           end
        end
	/*
        `RV32_SYSTEM : begin
           wb_src_sel_DX = `WB_SRC_CSR;
           wr_reg = (funct3 != `RV32_FUNCT3_PRIV);
           case (funct3)
             `RV32_FUNCT3_PRIV : begin
                if ((rs1 == 0) && (reg_to_wr_DX == 0)) begin
                   case (funct12)
                     `RV32_FUNCT12_ECALL : ecall = 1'b1;
                     `RV32_FUNCT12_EBREAK : ebreak = 1'b1;
                     `RV32_FUNCT12_ERET : begin
                        if (prv == 0)
                          illegal_instruction = 1'b1;
                        else
                          eret_unkilled = 1'b1;
                     end
                     default : illegal_instruction = 1'b1;
                   endcase // case (funct12)
                end // if ((rs1 == 0) && (reg_to_wr_DX == 0))
             end // case: `RV32_FUNCT3_PRIV
             `RV32_FUNCT3_CSRRW : csr_cmd = (rs1 == 0) ? `CSR_READ : `CSR_WRITE;
             `RV32_FUNCT3_CSRRS : csr_cmd = (rs1 == 0) ? `CSR_READ : `CSR_SET;
             `RV32_FUNCT3_CSRRC : csr_cmd = (rs1 == 0) ? `CSR_READ : `CSR_CLEAR;
             `RV32_FUNCT3_CSRRWI : csr_cmd = (rs1 == 0) ? `CSR_READ : `CSR_WRITE;
             `RV32_FUNCT3_CSRRSI : csr_cmd = (rs1 == 0) ? `CSR_READ : `CSR_SET;
             `RV32_FUNCT3_CSRRCI : csr_cmd = (rs1 == 0) ? `CSR_READ : `CSR_CLEAR;
             default : illegal_instruction = 1'b1;
           endcase // case (funct3)
        end
	 */
        `RV32_AUIPC : begin
           uses_rs1 = 1'b0;
           src_a_sel = `SRC_A_PC;
           imm_type = `IMM_U;
           wr_reg = 1'b1;
        end
        `RV32_LUI : begin
           uses_rs1 = 1'b0;
           src_a_sel = `SRC_A_ZERO;
           imm_type = `IMM_U;
           wr_reg = 1'b1;
        end
        default : begin
           illegal_instruction = 1'b1;
        end
      endcase // case (opcode)
   end // always @ (*)

   assign add_or_sub = ((opcode == `RV32_OP) && (funct7[5])) ? `ALU_OP_SUB : `ALU_OP_ADD;
   assign srl_or_sra = (funct7[5]) ? `ALU_OP_SRA : `ALU_OP_SRL;

   always @(*) begin
      case (funct3)
        `RV32_FUNCT3_ADD_SUB : alu_op_arith = add_or_sub;
        `RV32_FUNCT3_SLL : alu_op_arith = `ALU_OP_SLL;
        `RV32_FUNCT3_SLT : alu_op_arith = `ALU_OP_SLT;
        `RV32_FUNCT3_SLTU : alu_op_arith = `ALU_OP_SLTU;
        `RV32_FUNCT3_XOR : alu_op_arith = `ALU_OP_XOR;
        `RV32_FUNCT3_SRA_SRL : alu_op_arith = srl_or_sra;
        `RV32_FUNCT3_OR : alu_op_arith = `ALU_OP_OR;
        `RV32_FUNCT3_AND : alu_op_arith = `ALU_OP_AND;
        default : alu_op_arith = `ALU_OP_ADD;
      endcase // case (funct3)
   end // always @ begin


   //assign md_req_valid = uses_md;
   assign rs_ent_md = (
		       (funct3 == `RV32_FUNCT3_MUL) ||
		       (funct3 == `RV32_FUNCT3_MULH) ||
		       (funct3 == `RV32_FUNCT3_MULHSU) ||
		       (funct3 == `RV32_FUNCT3_MULHU)
		       ) ? `RS_ENT_MUL : `RS_ENT_DIV;
   
   always @(*) begin
      md_req_op = `MD_OP_MUL;
      md_req_in_1_signed = 0;
      md_req_in_2_signed = 0;
      md_req_out_sel = `MD_OUT_LO;
      case (funct3)
        `RV32_FUNCT3_MUL : begin
        end
        `RV32_FUNCT3_MULH : begin
           md_req_in_1_signed = 1;
           md_req_in_2_signed = 1;
           md_req_out_sel = `MD_OUT_HI;
        end
        `RV32_FUNCT3_MULHSU : begin
           md_req_in_1_signed = 1;
           md_req_out_sel = `MD_OUT_HI;
        end
        `RV32_FUNCT3_MULHU : begin
           md_req_out_sel = `MD_OUT_HI;
        end
        `RV32_FUNCT3_DIV : begin
           md_req_op = `MD_OP_DIV;
           md_req_in_1_signed = 1;
           md_req_in_2_signed = 1;
        end
        `RV32_FUNCT3_DIVU : begin
           md_req_op = `MD_OP_DIV;
        end
        `RV32_FUNCT3_REM : begin
           md_req_op = `MD_OP_REM;
           md_req_in_1_signed = 1;
           md_req_in_2_signed = 1;
           md_req_out_sel = `MD_OUT_REM;
        end
        `RV32_FUNCT3_REMU : begin
           md_req_op = `MD_OP_REM;
           md_req_out_sel = `MD_OUT_REM;
        end
      endcase
   end

   
endmodule // decoder
`default_nettype wire
/**************************************************************************************************/
/* Many-core processor project Arch Lab.                                               TOKYO TECH */
/**************************************************************************************************/
//`default_nettype none
/**************************************************************************************************/

/* Clock Frequency Definition                                                                     */
/* Clock Freq = (System Clock Freq) * (DCM_CLKFX_MULTIPLY) / (DCM_CLKFX_DIVIDE)                   */
/**************************************************************************************************/
`define SYSTEM_CLOCK_FREQ   200    // Atlys -> 100 MHz, Nexys4 -> 100 MHz, Virtex7 -> 200 MHz

`define DCM_CLKIN_PERIOD    5.000  // Atlys -> 10.000 ns
`define DCM_CLKFX_MULTIPLY  3      // CLKFX_MULTIPLY must be 2~32
`define DCM_CLKFX_DIVIDE    25     // CLKFX_DIVIDE   must be 1~32

`define MMCM_CLKIN1_PERIOD  5.000  // Nexys4 -> 10.000 ns, Virtex7 -> 5.000 ns
`define MMCM_VCO_MULTIPLY   8      // for VCO, 800-1600
`define MMCM_VCO_DIVIDE     2
`define MMCM_CLKOUT0_DIVIDE 16     // for user clock, 50  MHz
`define MMCM_CLKOUT1_DIVIDE 4      // for dram clock, 200 MHz


/* UART Definition                                                                                */
/**************************************************************************************************/
`define SERIAL_WCNT  'd50       // 24MHz/1.5Mbaud, parameter for UartRx and UartTx
`define APP_SIZE        8*1024  // application program load size in byte (64*16=1024KB)
`define SCD_SIZE       64*1024  // scheduling program  load size in byte (64* 1=  64KB)
`define IMG_SIZE     1088*1024  // full image file     load size in byte (64*17=1088KB)


/**************************************************************************************************/
//`default_nettype wire
/**************************************************************************************************/
`include "constants.vh"
`default_nettype none
//8KB Single PORT synchronous BRAM
module dmem
  (
   input wire 		      clk,
   input wire [`ADDR_LEN-1:0] addr,
   input wire [`DATA_LEN-1:0] wdata,
   input wire 		      we,
   output reg [`DATA_LEN-1:0] rdata
   );

   reg [`DATA_LEN-1:0] 	      mem [0:2047];
   
   always @ (posedge clk) begin
      rdata <= mem[addr[10:0]];
      if (we)
	      mem[addr] <= wdata;
   end
endmodule // dmem
`default_nettype wire
`include "constants.vh"
`default_nettype none
module true_dualport_ram #(
			   parameter ADDRLEN = 10,
			   parameter DATALEN = 2,
			   parameter DEPTH = 1024
			   )
   (
    input wire 		     clka,
    input wire [ADDRLEN-1:0] addra,
    output reg [DATALEN-1:0] rdataa,
    input wire [DATALEN-1:0] wdataa,
    input wire 		     wea,
    input wire 		     clkb,
    input wire [ADDRLEN-1:0] addrb,
    output reg [DATALEN-1:0] rdatab,
    input wire [DATALEN-1:0] wdatab,
    input wire 		     web
    );


   reg [DATALEN-1:0] 				  mem [0:DEPTH-1];
   
   always @ (posedge clka) begin
      rdataa <= mem[addra];
      if (wea) begin
	 mem[addra] <= wdataa;
      end
   end

   always @ (posedge clkb) begin
      rdatab <= mem[addrb];
      if (web) begin
	 mem[addrb] <= wdatab;
      end
   end
endmodule // true_dualport_ram

module true_dualport_ram_clear #(
				 parameter ADDRLEN = 10,
				 parameter DATALEN = 2,
				 parameter DEPTH = 1024
				 )
   (
    input wire 		     clka,
    input wire [ADDRLEN-1:0] addra,
    output reg [DATALEN-1:0] rdataa,
    input wire [DATALEN-1:0] wdataa,
    input wire 		     wea,
    input wire 		     clkb,
    input wire [ADDRLEN-1:0] addrb,
    output reg [DATALEN-1:0] rdatab,
    input wire [DATALEN-1:0] wdatab,
    input wire 		     web,
    input wire 		     clear
    );

   reg [DATALEN-1:0] 					mem [0:DEPTH-1];
   integer 						i;
   
   always @ (*) begin
      if (clear) begin
	 for (i=0; i<DEPTH; i=i+1)
	   mem[i] = 0;
      end
   end
   
   always @ (posedge clka) begin
      rdataa <= mem[addra];
      if (wea) begin
	 mem[addra] <= wdataa;
      end
   end

   always @ (posedge clkb) begin
      rdatab <= mem[addrb];
      if (web) begin
	 mem[addrb] <= wdatab;
      end
   end
endmodule // true_dualport_ram
`default_nettype wire
`include "constants.vh"
`include "alu_ops.vh"
`default_nettype none
module exunit_alu
  (
   input wire 			     clk,
   input wire 			     reset,
   input wire [`DATA_LEN-1:0] 	     ex_src1,
   input wire [`DATA_LEN-1:0] 	     ex_src2,
   input wire [`ADDR_LEN-1:0] 	     pc,
   input wire [`DATA_LEN-1:0] 	     imm,
   input wire 			     dstval,
   input wire [`SRC_A_SEL_WIDTH-1:0] src_a,
   input wire [`SRC_B_SEL_WIDTH-1:0] src_b,
   input wire [`ALU_OP_WIDTH-1:0]    alu_op,
   input wire [`SPECTAG_LEN-1:0]     spectag,
   input wire 			     specbit,
   input wire 			     issue,
   input wire 			     prmiss,
   input wire [`SPECTAG_LEN-1:0]     spectagfix,
   output wire [`DATA_LEN-1:0] 	     result,
   output wire 			     rrf_we,
   output wire 			     rob_we, //set finish
   output wire 			     kill_speculative
   );

   wire [`DATA_LEN-1:0] 	alusrc1;
   wire [`DATA_LEN-1:0] 	alusrc2;

   reg 				busy;

   assign rob_we = busy;
   assign rrf_we = busy & dstval;
   assign kill_speculative = ((spectag & spectagfix) != 0) && specbit && prmiss;
   
   always @ (posedge clk) begin
      if (reset) begin
	 busy <= 0;
      end else begin
	 busy <= issue;
      end
   end
   
   src_a_mux samx
     (
      .src_a_sel(src_a),
      .pc(pc),
      .rs1(ex_src1),
      .alu_src_a(alusrc1)
      );

   src_b_mux sbmx
     (
      .src_b_sel(src_b),
      .imm(imm),
      .rs2(ex_src2),
      .alu_src_b(alusrc2)
      );

   alu alice
     (
      .op(alu_op),
      .in1(alusrc1),
      .in2(alusrc2),
      .out(result)
      );
endmodule // exunit_alu
`default_nettype wire
   
`include "constants.vh"
`include "alu_ops.vh"
`include "rv32_opcodes.vh"
`default_nettype none
module exunit_branch
  (
   input wire 			  clk,
   input wire 			  reset,
   input wire [`DATA_LEN-1:0] 	  ex_src1,
   input wire [`DATA_LEN-1:0] 	  ex_src2,
   input wire [`ADDR_LEN-1:0] 	  pc,
   input wire [`DATA_LEN-1:0] 	  imm,
   input wire 			  dstval,
   input wire [`ALU_OP_WIDTH-1:0] alu_op,
   input wire [`SPECTAG_LEN-1:0]  spectag,
   input wire 			  specbit,
   input wire [`ADDR_LEN-1:0] 	  praddr,
   input wire [6:0] 		  opcode,
   input wire 			  issue,
   output wire [`DATA_LEN-1:0] 	  result,
   output wire 			  rrf_we,
   output wire 			  rob_we, //set finish
   output wire 			  prsuccess,
   output wire 			  prmiss,
   output wire [`ADDR_LEN-1:0] 	  jmpaddr,
   output wire [`ADDR_LEN-1:0] 	  jmpaddr_taken,
   output wire 			  brcond,
   output wire [`SPECTAG_LEN-1:0] tagregfix
   );

   reg 			       busy;
   
   wire [`DATA_LEN-1:0]        comprslt;
   wire 		       addrmatch = (jmpaddr == praddr) ? 1'b1 : 1'b0;

   
   assign rob_we = busy;
   assign rrf_we = busy & dstval;
   assign result = pc + 4;
   assign prsuccess = busy & addrmatch;
   assign prmiss = busy & ~addrmatch;
   assign jmpaddr = brcond ? jmpaddr_taken : (pc + 4);
   assign jmpaddr_taken = (((opcode == `RV32_JALR) ? ex_src1 : pc) + imm);
   
   assign brcond = ((opcode == `RV32_JAL) || (opcode == `RV32_JALR)) ?
			       1'b1 : comprslt[0];
   assign tagregfix = {spectag[0], spectag[`SPECTAG_LEN-1:1]};
   
   always @ (posedge clk) begin
      if (reset) begin
	 busy <= 0;
      end else begin
	 busy <= issue;
      end
   end
		  
   alu comparator
     (
      .op(alu_op),
      .in1(ex_src1),
      .in2(ex_src2),
      .out(comprslt)
      );
   
endmodule // exunit_branch

`default_nettype wire
`include "constants.vh"
`include "alu_ops.vh"
//`default_nettype none

module exunit_ldst
  (
   input wire 			 clk,
   input wire 			 reset,
   input wire [`DATA_LEN-1:0] 	 ex_src1,
   input wire [`DATA_LEN-1:0] 	 ex_src2,
   input wire [`ADDR_LEN-1:0] 	 pc,
   input wire [`DATA_LEN-1:0] 	 imm,
   input wire 			 dstval,
   input wire [`SPECTAG_LEN-1:0] spectag,
   input wire 			 specbit,
   input wire 			 issue,
   input wire 			 prmiss,
   input wire [`SPECTAG_LEN-1:0] spectagfix,
   input wire [`RRF_SEL-1:0] 	 rrftag,
   output wire [`DATA_LEN-1:0] 	 result,
   output wire 			 rrf_we,
   output wire 			 rob_we, //set finish
   output wire [`RRF_SEL-1:0] 	 wrrftag,
   output wire 			 kill_speculative,
   output wire 			 busy_next,
   //Signal StoreBuf
   output wire 			 stfin,
   //Store
   output wire 			 memoccupy_ld,
   input wire 			 fullsb,
   output wire [`DATA_LEN-1:0] 	 storedata,
   output wire [`ADDR_LEN-1:0] 	 storeaddr,
   //Load
   input wire 			 hitsb,
   output wire [`ADDR_LEN-1:0] 	 ldaddr,
   input wire [`DATA_LEN-1:0] 	 lddatasb,
   input wire [`DATA_LEN-1:0] 	 lddatamem
   );

   reg 				 busy;
   wire 			 clearbusy;
   wire [`ADDR_LEN-1:0] 	 effaddr;
   wire 			 killspec1;
   
   //LATCH
   reg 				 dstval_latch;
   reg [`RRF_SEL-1:0] 		 rrftag_latch;
   reg 				 specbit_latch;
   reg [`SPECTAG_LEN-1:0] 	 spectag_latch;
   reg [`DATA_LEN-1:0] 		 lddatasb_latch;
   reg 				 hitsb_latch;
   reg 				 insnvalid_latch;

   assign clearbusy = (killspec1 || dstval || (~dstval && ~fullsb)) ? 1'b1 : 1'b0;
   assign killspec1 = ((spectag & spectagfix) != 0) && specbit && prmiss;
   assign kill_speculative = ((spectag_latch & spectagfix) != 0) && specbit_latch && prmiss;
   assign result = hitsb_latch ? lddatasb_latch : lddatamem;
   assign rrf_we = dstval_latch & insnvalid_latch;
   assign rob_we = insnvalid_latch;
   assign wrrftag = rrftag_latch;
   assign busy_next = clearbusy ? 1'b0 : busy;
   assign stfin = ~killspec1 & busy & ~dstval;
   assign memoccupy_ld = ~killspec1 & busy & dstval;
   assign storedata = ex_src2;
   assign storeaddr = effaddr;
   assign ldaddr = effaddr;
   assign effaddr = ex_src1 + imm;
   
   always @ (posedge clk) begin
      if (reset | killspec1 | ~busy | (~dstval & fullsb)) begin
	 dstval_latch <= 0;
	 rrftag_latch <= 0;
	 specbit_latch <= 0;
	 spectag_latch <= 0;
	 lddatasb_latch <= 0;
	 hitsb_latch <= 0;
	 insnvalid_latch <= 0;
      end else begin
	 dstval_latch <= dstval;
	 rrftag_latch <= rrftag;
	 specbit_latch <= specbit;
	 spectag_latch <= spectag;
	 lddatasb_latch <= lddatasb;
	 hitsb_latch <= hitsb;
	 insnvalid_latch <= ~killspec1 & ((busy & dstval) |
					  (busy & ~dstval & ~fullsb));
      end
   end // always @ (posedge clk)

   always @ (posedge clk) begin
      if (reset | killspec1) begin
	 busy <= 0;
      end else begin
	 busy <= issue | busy_next;
      end
   end
endmodule // exunit_ldst

//`default_nettype none
`include "constants.vh"
`default_nettype none
module exunit_mul
  (
   input wire 			 clk,
   input wire 			 reset,
   input wire [`DATA_LEN-1:0] 	 ex_src1,
   input wire [`DATA_LEN-1:0] 	 ex_src2,
   input wire 			 dstval,
   input wire [`SPECTAG_LEN-1:0] spectag,
   input wire 			 specbit,
   input wire 			 src1_signed,
   input wire 			 src2_signed,
   input wire 			 sel_lohi,
   input wire 			 issue,
   input wire 			 prmiss,
   input wire [`SPECTAG_LEN-1:0] spectagfix,
   output wire [`DATA_LEN-1:0] 	 result,
   output wire 			 rrf_we,
   output wire 			 rob_we, //set finish
   output wire 			 kill_speculative
   );

   reg 			       busy;
   
   assign rob_we = busy;
   assign rrf_we = busy & dstval;
   assign kill_speculative = ((spectag & spectagfix) != 0) && specbit && prmiss;
   
   always @ (posedge clk) begin
      if (reset) begin
	 busy <= 0;
      end else begin
	 busy <= issue;
      end
   end
   
   multiplier bob
     (
      .src1(ex_src1),
      .src2(ex_src2),
      .src1_signed(src1_signed),
      .src2_signed(src2_signed),
      .sel_lohi(sel_lohi),
      .result(result)
      );
   
endmodule // exunit_mul

   
`default_nettype wire
`include "constants.vh"

/*
 ATTENTION!!!!!!!!!!!!!!!!!
 BHR in this code must change when spectag_len is changed
 */
`default_nettype none
module sel_bhrfix(
		  input wire [4:0] 		sel,
		  input wire [`GSH_BHR_LEN-1:0] bhr0,
		  input wire [`GSH_BHR_LEN-1:0] bhr1,
		  input wire [`GSH_BHR_LEN-1:0] bhr2,
		  input wire [`GSH_BHR_LEN-1:0] bhr3,
		  input wire [`GSH_BHR_LEN-1:0] bhr4,
		  output reg [`GSH_BHR_LEN-1:0] out
		  );
   always @ (*) begin
      out = 0;
      case (sel)
	5'b00001 : out = bhr0;
	5'b00010 : out = bhr1;
	5'b00100 : out = bhr2;
	5'b01000 : out = bhr3;
	5'b10000 : out = bhr4;
	default  : out = 0;
      endcase // case (sel)
   end
   
endmodule // sel_bhr

//PRTAG is tag of prmiss/success branch instruction's
module gshare_predictor
  (
   input wire 			 clk,
   input wire 			 reset,
   input wire [`ADDR_LEN-1:0] 	 pc,
   input wire 			 hit_bht,
   output wire 			 predict_cond,
   input wire 			 we,
   input wire 			 wcond,
   input wire [`GSH_PHT_SEL-1:0] went,
   input wire [`SPECTAG_LEN-1:0] mpft_valid,
   input wire 			 prmiss,
   input wire 			 prsuccess,
   input wire [`SPECTAG_LEN-1:0] prtag,
   output reg [`GSH_BHR_LEN-1:0] bhr_master,
   input wire [`SPECTAG_LEN-1:0] spectagnow
   );

   reg [`GSH_BHR_LEN-1:0] 	 bhr0;
   reg [`GSH_BHR_LEN-1:0] 	 bhr1;
   reg [`GSH_BHR_LEN-1:0] 	 bhr2;
   reg [`GSH_BHR_LEN-1:0] 	 bhr3;
   reg [`GSH_BHR_LEN-1:0] 	 bhr4;
   wire [`GSH_BHR_LEN-1:0] 	 bhr_fix;
   wire [1:0] 			 rif;
   wire [1:0] 			 rex;
   wire [1:0] 			 wex;
   wire [2:0] 			 wex_calc;
   
   sel_bhrfix sb(
		 .sel(prtag),
		 .bhr0(bhr0),
		 .bhr1(bhr1),
		 .bhr2(bhr2),
		 .bhr3(bhr3),
		 .bhr4(bhr4),
		 .out(bhr_fix)
		 );
   
   always @ (posedge clk) begin
      if (reset) begin
	 bhr0 <= 0;
	 bhr1 <= 0;
	 bhr2 <= 0;
	 bhr3 <= 0;
	 bhr4 <= 0;
	 bhr_master <= 0;
      end else if (prmiss) begin
	 bhr0 <= bhr_fix;
	 bhr1 <= bhr_fix;
	 bhr2 <= bhr_fix;
	 bhr3 <= bhr_fix;
	 bhr4 <= bhr_fix;
	 bhr_master <= bhr_fix;
      end else if (prsuccess) begin
	 bhr0 <= (prtag == 5'b00001) ? {bhr_master[`GSH_BHR_LEN-2:0], predict_cond} : bhr0; 
	 bhr1 <= (prtag == 5'b00010) ? {bhr_master[`GSH_BHR_LEN-2:0], predict_cond} : bhr1;
	 bhr2 <= (prtag == 5'b00100) ? {bhr_master[`GSH_BHR_LEN-2:0], predict_cond} : bhr2;
	 bhr3 <= (prtag == 5'b01000) ? {bhr_master[`GSH_BHR_LEN-2:0], predict_cond} : bhr3;
	 bhr4 <= (prtag == 5'b10000) ? {bhr_master[`GSH_BHR_LEN-2:0], predict_cond} : bhr4;
      end else if (hit_bht) begin
	 if (we & mpft_valid[0]) begin
	    bhr0 <= {bhr0[`GSH_BHR_LEN-2:0], predict_cond};
	 end
	 if (we & mpft_valid[1]) begin
	    bhr1 <= {bhr1[`GSH_BHR_LEN-2:0], predict_cond};
	 end
	 if (we & mpft_valid[2]) begin
	    bhr2 <= {bhr2[`GSH_BHR_LEN-2:0], predict_cond};
	 end
	 if (we & mpft_valid[3]) begin
	    bhr3 <= {bhr3[`GSH_BHR_LEN-2:0], predict_cond};
	 end
	 if (we & mpft_valid[4]) begin
	    bhr4 <= {bhr4[`GSH_BHR_LEN-2:0], predict_cond};
	 end
	 if (we) begin
	    bhr_master <= {bhr_master[`GSH_BHR_LEN-2:0], predict_cond};
	 end
      end
   end
   
   // rif is read data of pht in fetch stage, if rif > 1 =>  branch taken 
   assign predict_cond = (hit_bht && (rif > 2'b01)) ? 1'b1 : 1'b0;
   // 
   assign wex_calc = {1'b0, rex} + (wcond ? 3'b001 : 3'b111);
   // 
   assign wex = ((rex == 2'b00) && ~wcond) ? 2'b00 :
		((rex == 2'b11) && wcond) ? 2'b11 : wex_calc[1:0];

   pht prhisttbl
     (
      .clk(clk),
      .raddr_if(pc[2+:`GSH_BHR_LEN] ^ bhr_master),
      .raddr_ex(went),
      .waddr_ex(went),
      .rdata_if(rif),
      .rdata_ex(rex),
      .wdata_ex(wex),
      .we_ex(we)
      );
   

endmodule // gshare_predictor

module pht(
	   input wire 			 clk,
	   input wire [`GSH_PHT_SEL-1:0] raddr_if,
	   input wire [`GSH_PHT_SEL-1:0] raddr_ex,
	   input wire [`GSH_PHT_SEL-1:0] waddr_ex,
	   output wire [1:0] 		 rdata_if,
	   output wire [1:0] 		 rdata_ex,
	   input wire [1:0] 		 wdata_ex,
	   input wire 			 we_ex
	   );
   
   true_dualport_ram #(`GSH_PHT_SEL, 2, `GSH_PHT_NUM) pht0
     (
      .clka(~clk),
      .addra(raddr_if),
      .rdataa(rdata_if),
      .wdataa(),
      .wea(1'b0),
      .clkb(clk),
      .addrb(waddr_ex),
      .rdatab(),
      .wdatab(wdata_ex),
      .web(we_ex)
      );
   
   true_dualport_ram #(`GSH_PHT_SEL, 2, `GSH_PHT_NUM) pht1
     (
      .clka(~clk),
      .addra(raddr_ex),
      .rdataa(rdata_ex),
      .wdataa(),
      .wea(1'b0),
      .clkb(clk),
      .addrb(waddr_ex),
      .rdatab(),
      .wdatab(wdata_ex),
      .web(we_ex)
      );
   
endmodule // pht
`default_nettype wire
module imem_outa
  (
   input [27:0]       pc,
   output reg [127:0] idata
   );

   always @ (*) begin
      case(pc)
	28'h0: idata = 128'h00202023001081130010202304100093;
	28'h1: idata = 128'h0000000000000000ffdff06f00202423;
	default: idata = 128'h0;
      endcase // case (pc)
   end
endmodule // imem_outa

`include "constants.vh"
`default_nettype none
// 8KB Instruction Memory (32bit*4way)
module imem(
	    input wire 			 clk,
	    input wire [8:0] 		 addr,
	    output reg [`INSN_LEN*4-1:0] data
	    );
   reg [`INSN_LEN*4-1:0] 		 mem[0:511];
   always @ (posedge clk) begin
      data <= mem[addr];
   end
endmodule // imem

module imem_ld(
	       input wire 		    clk,
	       input wire [8:0] 	    addr,
	       output reg [4*`INSN_LEN-1:0] rdata,
	       input wire [4*`INSN_LEN-1:0] wdata,
	       input wire we
	       );
   reg [`INSN_LEN*4-1:0] 		 mem[0:511];
   always @ (posedge clk) begin
      rdata <= mem[addr];
      if (we) begin
	 mem[addr] <= wdata;
      end
   end
endmodule
`default_nettype wire
`include "constants.vh"
`default_nettype none
module imm_gen(
               input wire [`INSN_LEN-1:0] 	inst,
               input wire [`IMM_TYPE_WIDTH-1:0] imm_type,
               output reg [`DATA_LEN-1:0] 	imm
               );

   always @(*) begin
      case (imm_type)
        `IMM_I : imm = { {21{inst[31]}}, inst[30:25], inst[24:21], inst[20] };
        `IMM_S : imm = { {21{inst[31]}}, inst[30:25], inst[11:8], inst[7] };
        `IMM_U : imm = { inst[31], inst[30:20], inst[19:12], 12'b0 };
        `IMM_J : imm = { {12{inst[31]}}, inst[19:12], inst[20], inst[30:25], inst[24:21], 1'b0 };
        default : imm = { {21{inst[31]}}, inst[30:25], inst[24:21], inst[20] };
      endcase // case (imm_type)
   end

endmodule // imm_gen




`default_nettype wire
`include "constants.vh"
`default_nettype none
module tag_decoder
  (
   input wire [`SPECTAG_LEN-1:0] in,
   output reg [2:0] 		 out
   );

   always @ (*) begin
      out = 0;
      case (in)
	5'b00001: out = 0;
	5'b00010: out = 1;
	5'b00100: out = 2;
	5'b01000: out = 3;
	5'b10000: out = 4;
	default: out = 0;
      endcase // case (in)
   end
endmodule // tag_decoder

module miss_prediction_fix_table
  (
   input wire 			  clk,
   input wire 			  reset,
   output reg [`SPECTAG_LEN-1:0]  mpft_valid,
   input wire [`SPECTAG_LEN-1:0]  value_addr,
   output wire [`SPECTAG_LEN-1:0] mpft_value,
   input wire 			  prmiss,
   input wire 			  prsuccess,
   input wire [`SPECTAG_LEN-1:0]  prsuccess_tag,
   input wire [`SPECTAG_LEN-1:0]  setspec1_tag, //inst1_spectag
   input wire 			  setspec1_en, //inst1_isbranch & ~inst1_inv
   input wire [`SPECTAG_LEN-1:0]  setspec2_tag,
   input wire 			  setspec2_en
   );

   reg [`SPECTAG_LEN-1:0] 	  value0;
   reg [`SPECTAG_LEN-1:0] 	  value1;
   reg [`SPECTAG_LEN-1:0] 	  value2;
   reg [`SPECTAG_LEN-1:0] 	  value3;
   reg [`SPECTAG_LEN-1:0] 	  value4;

   wire [2:0] 			  val_idx;
   
   tag_decoder td(
		  .in(value_addr),
		  .out(val_idx)
		  );
   
   
   assign mpft_value = {
			value4[val_idx],
			value3[val_idx],
			value2[val_idx],
			value1[val_idx],
			value0[val_idx]
			};

   /*
    wire [`SPECTAG_LEN-1:0] value0_wdec =
    (~setspec1_tag[0] || ~setspec1_en ? 5'b0 :
    (setspec1_tag |
    ((setspec1_tag == 5'b00001) ? mpft_valid : 5'b0))) |
    (~setspec2_tag[0] || ~setspec2_en ? 5'b0 :
    (setspec2_tag |
    ((setspec2_tag == 5'b00001) ? mpft_valid : 5'b0)));
    */
   wire [`SPECTAG_LEN-1:0] 	  wdecdata = mpft_valid | (setspec1_en ? setspec1_tag : 0);

   wire [`SPECTAG_LEN-1:0] 	  value0_wdec =
				  (~setspec1_tag[0] || ~setspec1_en ? 5'b0 :
				   (setspec1_tag | 
				    ((setspec1_tag == 5'b00001) ? mpft_valid : 5'b0))) |
				  (~setspec2_tag[0] || ~setspec2_en ? 5'b0 :
				   (setspec2_tag |
				    ((setspec2_tag == 5'b00001) ? wdecdata : 5'b0)));
   
   wire [`SPECTAG_LEN-1:0] 	  value1_wdec =
				  (~setspec1_tag[1] || ~setspec1_en ? 5'b0 :
				   (setspec1_tag |
				    ((setspec1_tag == 5'b00010) ? mpft_valid : 5'b0))) |
				  (~setspec2_tag[1] || ~setspec2_en ? 5'b0 :
				   (setspec2_tag |
				    ((setspec2_tag == 5'b00010) ? wdecdata : 5'b0)));
   
   wire [`SPECTAG_LEN-1:0] 	  value2_wdec =
				  (~setspec1_tag[2] || ~setspec1_en ? 5'b0 :
				   (setspec1_tag |
				    ((setspec1_tag == 5'b00100) ? mpft_valid : 5'b0))) |
				  (~setspec2_tag[2] || ~setspec2_en ? 5'b0 :
				   (setspec2_tag |
				    ((setspec2_tag == 5'b00100) ? wdecdata : 5'b0)));
   
   wire [`SPECTAG_LEN-1:0] 	  value3_wdec =
				  (~setspec1_tag[3] || ~setspec1_en ? 5'b0 :
				   (setspec1_tag |
				    ((setspec1_tag == 5'b01000) ? mpft_valid : 5'b0))) |
				  (~setspec2_tag[3] || ~setspec2_en ? 5'b0 :
				   (setspec2_tag |
				    ((setspec2_tag == 5'b01000) ? wdecdata : 5'b0)));
   
   wire [`SPECTAG_LEN-1:0] 	  value4_wdec =
				  (~setspec1_tag[4] || ~setspec1_en ? 5'b0 :
				   (setspec1_tag |
				    ((setspec1_tag == 5'b10000) ? mpft_valid : 5'b0))) |
				  (~setspec2_tag[4] || ~setspec2_en ? 5'b0 :
				   (setspec2_tag |
				    ((setspec2_tag == 5'b10000) ? wdecdata : 5'b0)));
   
   wire [`SPECTAG_LEN-1:0] 	  value0_wprs =
				  (prsuccess_tag[0] ? 5'b0 : ~prsuccess_tag);
   wire [`SPECTAG_LEN-1:0] 	  value1_wprs =
				  (prsuccess_tag[1] ? 5'b0 : ~prsuccess_tag);
   wire [`SPECTAG_LEN-1:0] 	  value2_wprs =
				  (prsuccess_tag[2] ? 5'b0 : ~prsuccess_tag);
   wire [`SPECTAG_LEN-1:0] 	  value3_wprs =
				  (prsuccess_tag[3] ? 5'b0 : ~prsuccess_tag);
   wire [`SPECTAG_LEN-1:0] 	  value4_wprs =
				  (prsuccess_tag[4] ? 5'b0 : ~prsuccess_tag);
   
   always @ (posedge clk) begin
      if (reset | prmiss) begin
	 mpft_valid <= 0;
      end else if (prsuccess) begin
	 mpft_valid <= mpft_valid & ~prsuccess_tag;
      end else begin
	 mpft_valid <= mpft_valid | 
		       (setspec1_en ? setspec1_tag : 0) |
		       (setspec2_en ? setspec2_tag : 0);
      end
   end

   always @ (posedge clk) begin
      if (reset | prmiss) begin
	 value0 <= 0;
	 value1 <= 0;
	 value2 <= 0;
	 value3 <= 0;
	 value4 <= 0;
      end else begin
	 value0 <= prsuccess ? (value0 & value0_wprs) : (value0 | value0_wdec);
	 value1 <= prsuccess ? (value1 & value1_wprs) : (value1 | value1_wdec);
	 value2 <= prsuccess ? (value2 & value2_wprs) : (value2 | value2_wdec);
	 value3 <= prsuccess ? (value3 & value3_wprs) : (value3 | value3_wdec);
	 value4 <= prsuccess ? (value4 & value4_wprs) : (value4 | value4_wdec);
      end
   end
   
endmodule // miss_prediction_fix_table
`default_nettype wire
`include "constants.vh"
`include "rv32_opcodes.vh"
`include "alu_ops.vh"
`default_nettype none
module mux_4x1(
	       input wire [1:0] 	    sel,
	       input wire [2*`DATA_LEN-1:0] dat0,
	       input wire [2*`DATA_LEN-1:0] dat1,
	       input wire [2*`DATA_LEN-1:0] dat2,
	       input wire [2*`DATA_LEN-1:0] dat3,
	       output reg [2*`DATA_LEN-1:0] out
	       );
   always @(*) begin
      case(sel)
	0: begin
	   out = dat0;
	end
	1: begin
	   out = dat1;
	end
	2: begin
	   out = dat2;
	end
	3: begin
	   out = dat3;
	end
      endcase
   end
endmodule // mux_4x1

// sel_lohi = md_req_out_sel[0]
module multiplier(
		  input wire signed [`DATA_LEN-1:0] src1,
		  input wire signed [`DATA_LEN-1:0] src2,
		  input wire 			    src1_signed,
		  input wire 			    src2_signed,
		  input wire 			    sel_lohi,
		  output wire [`DATA_LEN-1:0] 	    result
		  );

   wire signed [`DATA_LEN:0] 			    src1_unsign = {1'b0, src1};
   wire signed [`DATA_LEN:0] 			    src2_unsign = {1'b0, src2};

   wire signed [2*`DATA_LEN-1:0] 		    res_ss = src1 * src2;
   wire signed [2*`DATA_LEN-1:0] 		    res_su = src1 * src2_unsign;
   wire signed [2*`DATA_LEN-1:0] 		    res_us = src1_unsign * src2;
   wire signed [2*`DATA_LEN-1:0] 		    res_uu = src1_unsign * src2_unsign;

   wire [2*`DATA_LEN-1:0] 			    res;

   mux_4x1 mxres(
		 .sel({src1_signed, src2_signed}),
		 .dat0(res_uu),
		 .dat1(res_us),
		 .dat2(res_su),
		 .dat3(res_ss),
		 .out(res)
		 );
   
   assign result = sel_lohi ? res[`DATA_LEN+:`DATA_LEN] : res[`DATA_LEN-1:0];
   
endmodule // multiplier


`default_nettype wire
`default_nettype none

module oldest_finder2 #(
			parameter ENTLEN = 1,
			parameter VALLEN = 8
			)
  (
   input wire [2*ENTLEN-1:0] entvec,
   input wire [2*VALLEN-1:0] valvec,
   output wire [ENTLEN-1:0]  oldent,
   output wire [VALLEN-1:0]  oldval
   );
   //VALLEN = RRF_SEL+sortbit+~rdy
   
   wire [ENTLEN-1:0] 	     ent1 = entvec[0+:ENTLEN];
   wire [ENTLEN-1:0] 	     ent2 = entvec[ENTLEN+:ENTLEN];
   wire [VALLEN-1:0] 	     val1 = valvec[0+:VALLEN];
   wire [VALLEN-1:0] 	     val2 = valvec[VALLEN+:VALLEN];

   assign oldent = (val1 < val2) ? ent1 : ent2;
   assign oldval = (val1 < val2) ? val1 : val2;

endmodule // oldest_finder2

module oldest_finder4 #(
			parameter ENTLEN = 2,
			parameter VALLEN = 8
			)
   (
    input wire [4*ENTLEN-1:0] entvec,
    input wire [4*VALLEN-1:0] valvec,
    output wire [ENTLEN-1:0]  oldent,
    output wire [VALLEN-1:0]  oldval
   );
   //VALLEN = RRF_SEL+sortbit+~rdy

   wire [ENTLEN-1:0] 	     oldent1;
   wire [ENTLEN-1:0] 	     oldent2;
   wire [VALLEN-1:0] 	     oldval1;
   wire [VALLEN-1:0] 	     oldval2;

   oldest_finder2 #(ENTLEN, VALLEN) of2_1
     (
      .entvec({entvec[ENTLEN+:ENTLEN], entvec[0+:ENTLEN]}),
      .valvec({valvec[VALLEN+:VALLEN], valvec[0+:VALLEN]}),
      .oldent(oldent1),
      .oldval(oldval1)
      );

   oldest_finder2 #(ENTLEN, VALLEN) of2_2
     (
      .entvec({entvec[3*ENTLEN+:ENTLEN], entvec[2*ENTLEN+:ENTLEN]}),
      .valvec({valvec[3*VALLEN+:VALLEN], valvec[2*VALLEN+:VALLEN]}),
      .oldent(oldent2),
      .oldval(oldval2)
      );

   oldest_finder2 #(ENTLEN, VALLEN) ofmas
     (
      .entvec({oldent2, oldent1}),
      .valvec({oldval2, oldval1}),
      .oldent(oldent),
      .oldval(oldval)
      );
   
endmodule // oldest_finder4

module oldest_finder8 #(
			parameter ENTLEN = 3,
			parameter VALLEN = 8
			)
   (
    input wire [8*ENTLEN-1:0] entvec,
    input wire [8*VALLEN-1:0] valvec,
    output wire [ENTLEN-1:0]  oldent,
    output wire [VALLEN-1:0]  oldval
   );
   //VALLEN = RRF_SEL+sortbit+~rdy

   wire [ENTLEN-1:0] 	     oldent1;
   wire [ENTLEN-1:0] 	     oldent2;
   wire [VALLEN-1:0] 	     oldval1;
   wire [VALLEN-1:0] 	     oldval2;
   
   oldest_finder4 #(ENTLEN, VALLEN) of4_1
     (
      .entvec({entvec[3*ENTLEN+:ENTLEN], entvec[2*ENTLEN+:ENTLEN],
	       entvec[ENTLEN+:ENTLEN], entvec[0+:ENTLEN]}),
      .valvec({valvec[3*VALLEN+:VALLEN], valvec[2*VALLEN+:VALLEN],
	       valvec[VALLEN+:VALLEN], valvec[0+:VALLEN]}),
      .oldent(oldent1),
      .oldval(oldval1)
      );

   oldest_finder4 #(ENTLEN, VALLEN) of4_2
     (
      .entvec({entvec[7*ENTLEN+:ENTLEN], entvec[6*ENTLEN+:ENTLEN],
	       entvec[5*ENTLEN+:ENTLEN], entvec[4*ENTLEN+:ENTLEN]}),
      .valvec({valvec[7*VALLEN+:VALLEN], valvec[6*VALLEN+:VALLEN],
	       valvec[5*VALLEN+:VALLEN], valvec[4*VALLEN+:VALLEN]}),
      .oldent(oldent2),
      .oldval(oldval2)
      );

   oldest_finder2 #(ENTLEN, VALLEN) ofmas
     (
      .entvec({oldent2, oldent1}),
      .valvec({oldval2, oldval1}),
      .oldent(oldent),
      .oldval(oldval)
      );
   
endmodule // oldest_finder8

`default_nettype wire
`include "constants.vh"
`default_nettype none
module pipeline_if
  (
   input wire 			  clk,
   input wire 			  reset,
   input wire [`ADDR_LEN-1:0] 	  pc,

   output wire 			  predict_cond,
   output wire [`ADDR_LEN-1:0] 	  npc,
   output wire [`INSN_LEN-1:0] 	  inst1,
   output wire [`INSN_LEN-1:0] 	  inst2,
   output wire 			  invalid2,

   input wire 			  btbpht_we,
   input wire [`ADDR_LEN-1:0] 	  btbpht_pc,
   input wire [`ADDR_LEN-1:0] 	  btb_jmpdst,
   input wire 			  pht_wcond,
   input wire [`SPECTAG_LEN-1:0]  mpft_valid,
   input wire [`GSH_BHR_LEN-1:0]  pht_bhr,
   input wire 			  prmiss,
   input wire 			  prsuccess,
   input wire [`SPECTAG_LEN-1:0]  prtag,

   output wire [`GSH_BHR_LEN-1:0] bhr,
   input wire [`SPECTAG_LEN-1:0]  spectagnow,
   input wire [4*`INSN_LEN-1:0]   idata
   );

   wire 			  hit;
   wire [`ADDR_LEN-1:0] 	  pred_pc;

   assign npc = (hit && predict_cond) ? pred_pc :
		invalid2 ? pc + 4 :
		pc + 8;
/*   
   imem instmem(
		.clk(~clk),
		.addr(pc[12:4]),
		.data(idata)
		);
*/
   /*
   imem_outa instmem(
		     .pc(pc[31:4]),
		     .idata(idata)
		     );
   */
   select_logic sellog(
		       .sel(pc[3:2]),
		       .idata(idata),
		       .inst1(inst1),
		       .inst2(inst2),
		       .invalid(invalid2)
		       );

   btb brtbl(
	     .clk(clk),
	     .reset(reset),
	     .pc(pc),
	     .hit(hit),
	     .jmpaddr(pred_pc),
	     .we(btbpht_we),
	     .jmpsrc(btbpht_pc),
	     .jmpdst(btb_jmpdst),
	     .invalid2(invalid2)
	     );

   gshare_predictor gsh
     (
      .clk(clk),
      .reset(reset),
      .pc(pc),
      .hit_bht(hit),
      .predict_cond(predict_cond),
      .we(btbpht_we),
      .wcond(pht_wcond),
      .went(btbpht_pc[2+:`GSH_BHR_LEN] ^ pht_bhr),
      .mpft_valid(mpft_valid),
      .prmiss(prmiss),
      .prsuccess(prsuccess),
      .prtag(prtag),
      .bhr_master(bhr),
      .spectagnow(spectagnow)
      );
   
endmodule // pipeline_pc


module select_logic
  (
   input wire [1:0] 		sel,
   input wire [4*`INSN_LEN-1:0] idata,
   output reg [`INSN_LEN-1:0] 	inst1,
   output reg [`INSN_LEN-1:0] 	inst2,
   output wire 			invalid
   );

// 只能取 32|10 , 不能 03|21|
   assign invalid = (sel[0] == 1'b1);
   
   always @ (*) begin
      inst1 = `INSN_LEN'h0;
      inst2 = `INSN_LEN'h0;
      
      case(sel)
	2'b00 : begin
	   inst1 = idata[31:0];
	   inst2 = idata[63:32];
	end
	2'b01 : begin
	   inst1 = idata[63:32];
	   inst2 = idata[95:64];
	end
	2'b10 : begin
	   inst1 = idata[95:64];
	   inst2 = idata[127:96];
	end
	2'b11 : begin
	   inst1 = idata[127:96];
	   inst2 = idata[31:0];
	end
      endcase // case (sel)
   end
   
endmodule // select_logic

`default_nettype wire
`include "constants.vh"
`include "alu_ops.vh"
`include "rv32_opcodes.vh"

`default_nettype none

module pipeline
  (
   input wire 			clk,
   input wire 			reset,
   output reg [`ADDR_LEN-1:0] 	pc,
   input wire [4*`INSN_LEN-1:0] idata,
   output wire [`DATA_LEN-1:0] 	dmem_wdata,
   output wire 			dmem_we,
   output wire [`ADDR_LEN-1:0] 	dmem_addr,
   input wire [`DATA_LEN-1:0] 	dmem_data
   );
   wire  stall_IF;
   wire  kill_IF;
   wire  stall_ID;
   wire  kill_ID;
   wire  stall_DP;
   wire  kill_DP;
//   reg [`ADDR_LEN-1:0] pc;

   //IF
   // Signal from pipe_if
   wire     	       prcond;
   wire [`ADDR_LEN-1:0] npc;
   wire [`INSN_LEN-1:0] inst1;
   wire [`INSN_LEN-1:0] inst2;
   wire 		invalid2_pipe;
   wire [`GSH_BHR_LEN-1:0] bhr;
   
   //Instruction Buffer
   reg 			   prcond_if;
   reg [`ADDR_LEN-1:0] 	   npc_if;
   reg [`ADDR_LEN-1:0] 	   pc_if;
   reg [`INSN_LEN-1:0] 	   inst1_if;
   reg [`INSN_LEN-1:0] 	   inst2_if;
   reg 			   inv1_if;
   reg 			   inv2_if;
   reg 			   bhr_if;
   wire 		   attachable;

   //ID
   //Decode Info1
   wire [`IMM_TYPE_WIDTH-1:0] imm_type_1;
   wire [`REG_SEL-1:0] 	      rs1_1;
   wire [`REG_SEL-1:0] 	      rs2_1;
   wire [`REG_SEL-1:0] 	      rd_1;
   wire [`SRC_A_SEL_WIDTH-1:0] src_a_sel_1;
   wire [`SRC_B_SEL_WIDTH-1:0] src_b_sel_1;
   wire 		       wr_reg_1;
   wire 		       uses_rs1_1;
   wire 		       uses_rs2_1;
   wire 		       illegal_instruction_1;
   wire [`ALU_OP_WIDTH-1:0]    alu_op_1;
   wire [`RS_ENT_SEL-1:0]      rs_ent_1;
   wire [2:0] 		       dmem_size_1;
   wire [`MEM_TYPE_WIDTH-1:0]  dmem_type_1;			  
   wire [`MD_OP_WIDTH-1:0]     md_req_op_1;
   wire 		       md_req_in_1_signed_1;
   wire 		       md_req_in_2_signed_1;
   wire [`MD_OUT_SEL_WIDTH-1:0] md_req_out_sel_1;
   //Decode Info2
   wire [`IMM_TYPE_WIDTH-1:0] 	imm_type_2;
   wire [`REG_SEL-1:0] 		rs1_2;
   wire [`REG_SEL-1:0] 		rs2_2;
   wire [`REG_SEL-1:0] 		rd_2;
   wire [`SRC_A_SEL_WIDTH-1:0] 	src_a_sel_2;
   wire [`SRC_B_SEL_WIDTH-1:0] 	src_b_sel_2;
   wire 			wr_reg_2;
   wire 			uses_rs1_2;
   wire 			uses_rs2_2;
   wire 			illegal_instruction_2;
   wire [`ALU_OP_WIDTH-1:0] 	alu_op_2;
   wire [`RS_ENT_SEL-1:0] 	rs_ent_2;
   wire [2:0] 			dmem_size_2;
   wire [`MEM_TYPE_WIDTH-1:0] 	dmem_type_2;			  
   wire [`MD_OP_WIDTH-1:0] 	md_req_op_2;
   wire 			md_req_in_1_signed_2;
   wire 			md_req_in_2_signed_2;
   wire [`MD_OUT_SEL_WIDTH-1:0] md_req_out_sel_2;
   //Additional Info
   wire [`SPECTAG_LEN-1:0] 	sptag1;
   wire [`SPECTAG_LEN-1:0] 	sptag2;
   wire [`SPECTAG_LEN-1:0] 	tagreg;
   wire 			spec1;
   wire 			spec2;
   wire 			isbranch1;
   wire 			isbranch2;
   wire 			branchvalid1;
   wire 			branchvalid2;
   
   //Latch
   //Decode Info1
   reg [`IMM_TYPE_WIDTH-1:0] 	imm_type_1_id;
   reg [`REG_SEL-1:0] 		rs1_1_id;
   reg [`REG_SEL-1:0] 		rs2_1_id;
   reg [`REG_SEL-1:0] 		rd_1_id;
   reg [`SRC_A_SEL_WIDTH-1:0] 	src_a_sel_1_id;
   reg [`SRC_B_SEL_WIDTH-1:0] 	src_b_sel_1_id;
   reg 				wr_reg_1_id;
   reg 				uses_rs1_1_id;
   reg 				uses_rs2_1_id;
   reg 				illegal_instruction_1_id;
   reg [`ALU_OP_WIDTH-1:0] 	alu_op_1_id;
   reg [`RS_ENT_SEL-1:0] 	rs_ent_1_id;
   reg [2:0] 			dmem_size_1_id;
   reg [`MEM_TYPE_WIDTH-1:0] 	dmem_type_1_id;			  
   reg [`MD_OP_WIDTH-1:0] 	md_req_op_1_id;
   reg 				md_req_in_1_signed_1_id;
   reg 				md_req_in_2_signed_1_id;
   reg [`MD_OUT_SEL_WIDTH-1:0] 	md_req_out_sel_1_id;
   //Decode Info2
   reg [`IMM_TYPE_WIDTH-1:0] 	imm_type_2_id;
   reg [`REG_SEL-1:0] 		rs1_2_id;
   reg [`REG_SEL-1:0] 		rs2_2_id;
   reg [`REG_SEL-1:0] 		rd_2_id;
   reg [`SRC_A_SEL_WIDTH-1:0] 	src_a_sel_2_id;
   reg [`SRC_B_SEL_WIDTH-1:0] 	src_b_sel_2_id;
   reg 				wr_reg_2_id;
   reg 				uses_rs1_2_id;
   reg 				uses_rs2_2_id;
   reg 				illegal_instruction_2_id;
   reg [`ALU_OP_WIDTH-1:0] 	alu_op_2_id;
   reg [`RS_ENT_SEL-1:0] 	rs_ent_2_id;
   reg [2:0] 			dmem_size_2_id;
   reg [`MEM_TYPE_WIDTH-1:0] 	dmem_type_2_id;			  
   reg [`MD_OP_WIDTH-1:0] 	md_req_op_2_id;
   reg 				md_req_in_1_signed_2_id;
   reg 				md_req_in_2_signed_2_id;
   reg [`MD_OUT_SEL_WIDTH-1:0] 	md_req_out_sel_2_id;
   //Additional Info
   reg 				rs1_2_eq_dst1_id;
   reg 				rs2_2_eq_dst1_id;
   reg [`SPECTAG_LEN-1:0] 	sptag1_id;
   reg [`SPECTAG_LEN-1:0] 	sptag2_id;
   reg [`SPECTAG_LEN-1:0] 	tagreg_id;
   reg 				spec1_id;
   reg 				spec2_id;
   reg [`INSN_LEN-1:0] 		inst1_id;
   reg [`INSN_LEN-1:0] 		inst2_id;
   reg 				prcond1_id;
   reg 				prcond2_id;
   reg 				inv1_id;
   reg 				inv2_id;
   reg [`ADDR_LEN-1:0] 		praddr1_id;
   reg [`ADDR_LEN-1:0] 		praddr2_id;
   reg [`ADDR_LEN-1:0] 		pc_id;
   reg [`GSH_BHR_LEN-1:0] 	bhr_id;
   reg 				isbranch1_id;
   reg 				isbranch2_id;

   //DP
   //Source Operand Manager wire
   wire [`DATA_LEN-1:0] opr1_1;
   wire [`DATA_LEN-1:0] opr2_1;
   wire [`DATA_LEN-1:0] opr1_2;
   wire [`DATA_LEN-1:0] opr2_2;
   wire 		rdy1_1;
   wire 		rdy2_1;
   wire 		rdy1_2;
   wire 		rdy2_2;

   //rrf_FL wire
   wire 		alloc_rrf;
   wire [`RRF_SEL-1:0] 	dst1_renamed;
   wire [`RRF_SEL-1:0] 	dst2_renamed;
   wire [`RRF_SEL:0] 	freenum;
   wire [`RRF_SEL-1:0] 	rrfptr;
   wire [`RRF_SEL-1:0] 	rrftagfix;

   //arf wire 
   wire [`RRF_SEL-1:0] 	rs1_1tag;
   wire [`RRF_SEL-1:0] 	rs2_1tag;
   wire [`RRF_SEL-1:0] 	rs1_2tag;
   wire [`RRF_SEL-1:0] 	rs2_2tag;
   wire [`DATA_LEN-1:0] adat1_1;
   wire [`DATA_LEN-1:0] adat2_1;
   wire [`DATA_LEN-1:0] adat1_2;
   wire [`DATA_LEN-1:0] adat2_2;
   wire 		abusy1_1;
   wire 		abusy2_1;
   wire 		abusy1_2;
   wire 		abusy2_2;

   //rrf wire
   wire [`DATA_LEN-1:0] rdat1_1;
   wire [`DATA_LEN-1:0] rdat2_1;
   wire [`DATA_LEN-1:0] rdat1_2;
   wire [`DATA_LEN-1:0] rdat2_2;
   wire 		rvalid1_1;
   wire 		rvalid2_1;
   wire 		rvalid1_2;
   wire 		rvalid2_2;
   wire [`DATA_LEN-1:0] com1data;
   wire [`DATA_LEN-1:0] com2data;
   
   //Src Manager wire
   wire [`DATA_LEN-1:0] src1_1; //To reservation station
   wire [`DATA_LEN-1:0] src2_1; 
   wire [`DATA_LEN-1:0] src1_2;
   wire [`DATA_LEN-1:0] src2_2;
   wire 		resolved1_1;
   wire 		resolved2_1;
   wire 		resolved1_2;
   wire 		resolved2_2;

   //Immgen wire
   wire [`DATA_LEN-1:0] imm1; // To reservation station
   wire [`DATA_LEN-1:0] imm2;
   //BrImmgen wire
   wire [`DATA_LEN-1:0] brimm1; //To reservation station
   wire [`DATA_LEN-1:0] brimm2;
   
   //RS Request Generator wire
   wire 		req1_alu;
   wire 		req2_alu;
   wire [1:0] 		req_alunum;
   wire 		req1_branch;
   wire 		req2_branch;
   wire [1:0] 		req_branchnum;
   wire 		req1_mul;
   wire 		req2_mul;
   wire [1:0] 		req_mulnum;
   wire 		req1_ldst;
   wire 		req2_ldst;
   wire [1:0] 		req_ldstnum;

   wire [`ALU_ENT_SEL:0] allocent1_alu;
   wire [`ALU_ENT_SEL:0] allocent2_alu;
   wire 		 rsalu1_we1;
   wire 		 rsalu1_we2;
   wire 		 rsalu2_we1;
   wire 		 rsalu2_we2;
   wire [`ALU_ENT_NUM-1:0] busyvec_alu1;
   wire [`ALU_ENT_NUM-1:0] busyvec_alu2;
   wire [2*`ALU_ENT_NUM-1:0] busyvec_alu;
   wire [`ALU_ENT_NUM:0]     ready_alu;

   wire 		   issuevalid_alu1;
   wire [`ALU_ENT_SEL-1:0] issueent_alu1;
   wire 		   issue_alu1;
   wire 		   issuevalid_alu2;
   wire [`ALU_ENT_SEL-1:0] issueent_alu2;
   wire 		   issue_alu2;
   wire 		   allocatable_alu;
   wire [`ALU_ENT_NUM*(`RRF_SEL+2)-1:0] histvect1;
   wire [`ALU_ENT_NUM*(`RRF_SEL+2)-1:0] histvect2;
   wire [`RRF_SEL+1:0] 			entval_alu1;
   wire [`RRF_SEL+1:0] 			entval_alu2;
   
   wire 				nextrrfcyc;

   wire [`DATA_LEN-1:0]    ex_src1_alu1;
   wire [`DATA_LEN-1:0]    ex_src2_alu1;
   wire [`ALU_ENT_NUM-1:0] ready_alu1;
   wire [`ADDR_LEN-1:0]    pc_alu1;
   wire [`DATA_LEN-1:0]    imm_alu1;
   wire [`RRF_SEL-1:0] 	   rrftag_alu1;
   wire 		   dstval_alu1;
   wire [`SRC_A_SEL_WIDTH-1:0] src_a_alu1;
   wire [`SRC_B_SEL_WIDTH-1:0] src_b_alu1;
   wire [`ALU_OP_WIDTH-1:0]    alu_op_alu1;
   wire [`SPECTAG_LEN-1:0]     spectag_alu1;
   wire 		       specbit_alu1;

   wire [`DATA_LEN-1:0]        ex_src1_alu2;
   wire [`DATA_LEN-1:0]        ex_src2_alu2;
   wire [`ALU_ENT_NUM-1:0]     ready_alu2;
   wire [`ADDR_LEN-1:0]        pc_alu2;
   wire [`DATA_LEN-1:0]        imm_alu2;
   wire [`RRF_SEL-1:0] 	       rrftag_alu2;
   wire 		       dstval_alu2;
   wire [`SRC_A_SEL_WIDTH-1:0] src_a_alu2;
   wire [`SRC_B_SEL_WIDTH-1:0] src_b_alu2;
   wire [`ALU_OP_WIDTH-1:0]    alu_op_alu2;
   wire [`SPECTAG_LEN-1:0]     spectag_alu2;
   wire 		       specbit_alu2;
   
   wire [`LDST_ENT_SEL-1:0]    allocent1_ldst;
   wire [`LDST_ENT_SEL-1:0]    allocent2_ldst;
   wire [`LDST_ENT_NUM-1:0]    busyvec_ldst;
   wire [`LDST_ENT_NUM-1:0]    prbusyvec_next_ldst;
   wire [`LDST_ENT_NUM-1:0]    ready_ldst;
   wire 		       issuevalid_ldst;
   wire [`LDST_ENT_SEL-1:0]    issueent_ldst;
   wire 		       issue_ldst;
   wire 		       allocatable_ldst;

   wire [`DATA_LEN-1:0]        ex_src1_ldst;
   wire [`DATA_LEN-1:0]        ex_src2_ldst;
   wire [`ADDR_LEN-1:0]        pc_ldst;
   wire [`DATA_LEN-1:0]        imm_ldst;
   wire [`RRF_SEL-1:0] 	       rrftag_ldst;
   wire 		       dstval_ldst;
   wire [`SPECTAG_LEN-1:0]     spectag_ldst;
   wire 		       specbit_ldst;

   wire [`BRANCH_ENT_SEL-1:0]  allocent1_branch;
   wire [`BRANCH_ENT_SEL-1:0]  allocent2_branch;
   wire [`BRANCH_ENT_NUM-1:0]  busyvec_branch;
   wire [`BRANCH_ENT_NUM-1:0]  prbusyvec_next_branch;
   wire [`BRANCH_ENT_NUM-1:0]  ready_branch;
   wire 		       issuevalid_branch;
   wire [`BRANCH_ENT_SEL-1:0]  issueent_branch;
   wire 		       issue_branch;
   wire 		       allocatable_branch;

   wire [`DATA_LEN-1:0]        ex_src1_branch;
   wire [`DATA_LEN-1:0]        ex_src2_branch;
   wire [`ADDR_LEN-1:0]        pc_branch;
   wire [`DATA_LEN-1:0]        imm_branch;
   wire [`RRF_SEL-1:0] 	       rrftag_branch;
   wire 		       dstval_branch;
   wire [`ALU_OP_WIDTH-1:0]    alu_op_branch;
   wire [`SPECTAG_LEN-1:0]     spectag_branch;
   wire 		       specbit_branch;
   wire [`GSH_BHR_LEN-1:0]     bhr_branch;
   wire 		       prcond_branch;
   wire [`ADDR_LEN-1:0]        praddr_branch;
   wire [6:0] 		       opcode_branch;

   wire [`MUL_ENT_SEL-1:0]       allocent1_mul;
   wire [`MUL_ENT_SEL-1:0]       allocent2_mul;
   wire [`MUL_ENT_NUM-1:0]     busyvec_mul;
   wire [`MUL_ENT_NUM-1:0]     ready_mul;
   wire 		       issuevalid_mul;
   wire [`MUL_ENT_SEL-1:0]     issueent_mul;
   wire 		       issue_mul;
   wire 		       allocatable_mul;

   wire [`DATA_LEN-1:0]        ex_src1_mul;
   wire [`DATA_LEN-1:0]        ex_src2_mul;
   wire [`ADDR_LEN-1:0]        pc_mul;
   wire [`RRF_SEL-1:0] 	       rrftag_mul;
   wire 		       dstval_mul;
   wire [`SPECTAG_LEN-1:0]     spectag_mul;
   wire 		       specbit_mul;
   wire 		       src1_signed_mul;
   wire 		       src2_signed_mul;
   wire 		       sel_lohi_mul;

   //EX
   //ALU1
   wire [`DATA_LEN-1:0]        result_alu1;
   wire 		       rrfwe_alu1;
   wire 		       robwe_alu1;
   wire 		       kill_speculative_alu1;

   reg [`DATA_LEN-1:0] 	       buf_ex_src1_alu1;
   reg [`DATA_LEN-1:0] 	       buf_ex_src2_alu1;
   reg [`ADDR_LEN-1:0] 	       buf_pc_alu1;
   reg [`DATA_LEN-1:0] 	       buf_imm_alu1;
   reg [`RRF_SEL-1:0] 	       buf_rrftag_alu1;
   reg 			       buf_dstval_alu1;
   reg [`SRC_A_SEL_WIDTH-1:0]  buf_src_a_alu1;
   reg [`SRC_B_SEL_WIDTH-1:0]  buf_src_b_alu1;
   reg [`ALU_OP_WIDTH-1:0]     buf_alu_op_alu1;
   reg [`SPECTAG_LEN-1:0]      buf_spectag_alu1;
   reg 			       buf_specbit_alu1;
   //ALU2
   wire [`DATA_LEN-1:0]        result_alu2;
   wire 		       rrfwe_alu2;
   wire 		       robwe_alu2;
   wire 		       kill_speculative_alu2;

   reg [`DATA_LEN-1:0] 	       buf_ex_src1_alu2;
   reg [`DATA_LEN-1:0] 	       buf_ex_src2_alu2;
   reg [`ADDR_LEN-1:0] 	       buf_pc_alu2;
   reg [`DATA_LEN-1:0] 	       buf_imm_alu2;
   reg [`RRF_SEL-1:0] 	       buf_rrftag_alu2;
   reg 			       buf_dstval_alu2;
   reg [`SRC_A_SEL_WIDTH-1:0]  buf_src_a_alu2;
   reg [`SRC_B_SEL_WIDTH-1:0]  buf_src_b_alu2;
   reg [`ALU_OP_WIDTH-1:0]     buf_alu_op_alu2;
   reg [`SPECTAG_LEN-1:0]      buf_spectag_alu2;
   reg 			       buf_specbit_alu2;

   //LDST
   wire [`DATA_LEN-1:0]        result_ldst;
   wire 		       rrfwe_ldst;
   wire 		       robwe_ldst;
   wire [`RRF_SEL-1:0] 	       wrrftag_ldst;
   wire 		       kill_speculative_ldst;
   wire 		       busy_next_ldst;

   //wire [`DATA_LEN-1:0]        dmem_data;
   /*
   wire [`DATA_LEN-1:0]        dmem_wdata;
   wire 		       dmem_we;
   wire [`ADDR_LEN-1:0]        dmem_addr;
    */
   wire 		       sb_full;
   wire 		       hitsb;
   wire 		       memoccupy_ld;
   wire [`ADDR_LEN-1:0]        ldaddr;
   wire [`DATA_LEN-1:0]        lddatasb;
   wire [`ADDR_LEN-1:0]        retaddr;
   wire [`DATA_LEN-1:0]        storedata;
   wire [`ADDR_LEN-1:0]        storeaddr;
   wire 		       stfin;
   
   reg [`DATA_LEN-1:0] 	       buf_ex_src1_ldst;
   reg [`DATA_LEN-1:0] 	       buf_ex_src2_ldst;
   reg [`ADDR_LEN-1:0] 	       buf_pc_ldst;
   reg [`DATA_LEN-1:0] 	       buf_imm_ldst;
   reg [`RRF_SEL-1:0] 	       buf_rrftag_ldst;
   reg 			       buf_dstval_ldst;
   reg [`SPECTAG_LEN-1:0]      buf_spectag_ldst;
   reg 			       buf_specbit_ldst;

   //MUL
   wire [`DATA_LEN-1:0]        result_mul;
   wire 		       rrfwe_mul;
   wire 		       robwe_mul;
   wire 		       kill_speculative_mul;

   reg [`DATA_LEN-1:0] 	       buf_ex_src1_mul;
   reg [`DATA_LEN-1:0] 	       buf_ex_src2_mul;
   reg [`ADDR_LEN-1:0] 	       buf_pc_mul;
   reg [`RRF_SEL-1:0] 	       buf_rrftag_mul;
   reg 			       buf_dstval_mul;
   reg [`SPECTAG_LEN-1:0]      buf_spectag_mul;
   reg 			       buf_specbit_mul;
   reg 			       buf_src1_signed_mul;
   reg 			       buf_src2_signed_mul;
   reg 			       buf_sel_lohi_mul;
   
   //BRANCH
   wire 		       prmiss;
   wire 		       prsuccess;
   wire [`ADDR_LEN-1:0]        jmpaddr;
   wire [`ADDR_LEN-1:0]        jmpaddr_taken;
   wire 		       brcond;
   wire [`SPECTAG_LEN-1:0]     tagregfix;
   
   wire [`DATA_LEN-1:0]        result_branch;
   wire 		       rrfwe_branch;
   wire 		       robwe_branch;
   
   reg [`DATA_LEN-1:0] 	       buf_ex_src1_branch;
   reg [`DATA_LEN-1:0] 	       buf_ex_src2_branch;
   reg [`ADDR_LEN-1:0] 	       buf_pc_branch;
   reg [`DATA_LEN-1:0] 	       buf_imm_branch;
   reg [`RRF_SEL-1:0] 	       buf_rrftag_branch;
   reg 			       buf_dstval_branch;
   reg [`ALU_OP_WIDTH-1:0]     buf_alu_op_branch;
   reg [`SPECTAG_LEN-1:0]      buf_spectag_branch;
   reg 			       buf_specbit_branch;
   reg [`ADDR_LEN-1:0] 	       buf_praddr_branch;
   reg [6:0] 		       buf_opcode_branch;
   
   //miss prediction fix table
   wire [`SPECTAG_LEN-1:0] mpft_valid;
   wire [`SPECTAG_LEN-1:0] spectagfix;

   //COM
   wire [`RRF_SEL-1:0] 	   comptr;
   wire [`RRF_SEL-1:0] 	   comptr2;
   wire [1:0] 		   comnum;
   wire 		   stcommit;
   wire 		   arfwe1;
   wire 		   arfwe2;
   wire [`REG_SEL-1:0] 	   dstarf1;
   wire [`REG_SEL-1:0] 	   dstarf2;
   wire [`ADDR_LEN-1:0]    pc_combranch;
   wire [`GSH_BHR_LEN-1:0] bhr_combranch;
   wire 		   brcond_combranch;
   wire 		   combranch;
   wire [`ADDR_LEN-1:0]    jmpaddr_combranch;
   
   //IF Stage********************************************************
//   assign stall_IF = stall_ID;
//   assign kill_IF = prmiss;
   assign stall_IF = stall_ID | stall_DP;
   assign kill_IF = prmiss;
   
   always @ (posedge clk) begin
      if (reset) begin
	 pc <= `ENTRY_POINT;
      end else if (prmiss) begin
	 pc <= jmpaddr;
      end else if (stall_IF) begin
	 pc <= pc;
      end else begin
	 pc <= npc;
      end
   end

   
   pipeline_if pipe_if(
		       .clk(clk),
		       .reset(reset),
		       .pc(pc),
		       .predict_cond(prcond),
		       .npc(npc),
		       .inst1(inst1),
		       .inst2(inst2),
		       .invalid2(invalid2_pipe),
		       .btbpht_we(combranch),
		       .btbpht_pc(pc_combranch),
		       .btb_jmpdst(jmpaddr_combranch),
		       .pht_wcond(brcond_combranch),
		       .mpft_valid(mpft_valid),
		       .pht_bhr(bhr_combranch), //when PHT write
		       .prmiss(prmiss),
		       .prsuccess(prsuccess),
		       .prtag(buf_spectag_branch),
		       .bhr(bhr),
		       .spectagnow(tagreg),
		       .idata(idata)
		       );

   always @ (posedge clk) begin
      if (reset | kill_IF) begin
	 prcond_if <= 0;
	 npc_if <= 0;
	 pc_if <= 0;
	 inst1_if <= 0;
	 inst2_if <= 0;
	 inv1_if <= 1;
	 inv2_if <= 1;
	 bhr_if <= 0;
	 
      end else if (~stall_IF) begin
	 prcond_if <= prcond;
	 npc_if <= npc;
	 pc_if <= pc;
	 inst1_if <= inst1;
	 inst2_if <= inst2;
	 inv1_if <= 0;
	 inv2_if <= invalid2_pipe;
	 bhr_if <= bhr;
	 
      end
   end // always @ (posedge clk)

   //ID Stage********************************************************
//   assign stall_ID = stall_DP | ~attachable | (prsuccess & (isbranch1 | isbranch2));
//   assign kill_ID = prmiss;
   assign stall_ID = ~attachable | prsuccess;
   assign kill_ID = (stall_ID & ~stall_DP) | prmiss;
   
   assign isbranch1 = (~inv1_if && (rs_ent_1 == `RS_ENT_BRANCH)) ?
		      1'b1 : 1'b0;
   assign isbranch2 = (~inv2_if && (rs_ent_2 == `RS_ENT_BRANCH)) ?
		      1'b1 : 1'b0;
   assign branchvalid1 = isbranch1 & prcond_if;
   assign branchvalid2 = isbranch2 & ~branchvalid1;
   
   tag_generator taggen(
			.clk(clk),
			.reset(reset),
			.branchvalid1(isbranch1),
			.branchvalid2(branchvalid2),
			.prmiss(prmiss),
			.prsuccess(prsuccess),
			.enable(~stall_ID & ~stall_DP),
			.tagregfix(tagregfix),
			.sptag1(sptag1),
			.sptag2(sptag2),
			.speculative1(spec1),
			.speculative2(spec2),
			.attachable(attachable),
			.tagreg(tagreg)
			);
   
   decoder dec1(
		.inst(inst1_if),
		.imm_type(imm_type_1),
		.rs1(rs1_1),
		.rs2(rs2_1),
		.rd(rd_1),
		.src_a_sel(src_a_sel_1),
		.src_b_sel(src_b_sel_1),
		.wr_reg(wr_reg_1),
		.uses_rs1(uses_rs1_1),
		.uses_rs2(uses_rs2_1),
		.illegal_instruction(illegal_instruction_1),
		.alu_op(alu_op_1),
		.rs_ent(rs_ent_1),
		.dmem_size(dmem_size_1),
		.dmem_type(dmem_type_1),
		.md_req_op(md_req_op_1),
		.md_req_in_1_signed(md_req_in_1_signed_1),
		.md_req_in_2_signed(md_req_in_2_signed_1),
		.md_req_out_sel(md_req_out_sel_1)
		);

   decoder dec2(
		.inst(inst2_if),
		.imm_type(imm_type_2),
		.rs1(rs1_2),
		.rs2(rs2_2),
		.rd(rd_2),
		.src_a_sel(src_a_sel_2),
		.src_b_sel(src_b_sel_2),
		.wr_reg(wr_reg_2),
		.uses_rs1(uses_rs1_2),
		.uses_rs2(uses_rs2_2),
		.illegal_instruction(illegal_instruction_2),
		.alu_op(alu_op_2),
		.rs_ent(rs_ent_2),
		.dmem_size(dmem_size_2),
		.dmem_type(dmem_type_2),
		.md_req_op(md_req_op_2),
		.md_req_in_1_signed(md_req_in_1_signed_2),
		.md_req_in_2_signed(md_req_in_2_signed_2),
		.md_req_out_sel(md_req_out_sel_2)
		);

   always @ (posedge clk) begin
      if (reset | kill_ID) begin
	 imm_type_1_id <= 0;
	 rs1_1_id <= 0;
	 rs2_1_id <= 0;
	 rd_1_id <= 0;
	 src_a_sel_1_id <= 0;
	 src_b_sel_1_id <= 0;
	 wr_reg_1_id <= 0;
	 uses_rs1_1_id <= 0;
	 uses_rs2_1_id <= 0;
	 illegal_instruction_1_id <= 0;
	 alu_op_1_id <= 0;
	 rs_ent_1_id <= 0;
	 dmem_size_1_id <= 0;
	 dmem_type_1_id <= 0;			  
	 md_req_op_1_id <= 0;
	 md_req_in_1_signed_1_id <= 0;
	 md_req_in_2_signed_1_id <= 0;
	 md_req_out_sel_1_id <= 0;
	 imm_type_2_id <= 0;
	 rs1_2_id <= 0;
	 rs2_2_id <= 0;
	 rd_2_id <= 0;
	 src_a_sel_2_id <= 0;
	 src_b_sel_2_id <= 0;
	 wr_reg_2_id <= 0;
	 uses_rs1_2_id <= 0;
	 uses_rs2_2_id <= 0;
	 illegal_instruction_2_id <= 0;
	 alu_op_2_id <= 0;
	 rs_ent_2_id <= 0;
	 dmem_size_2_id <= 0;
	 dmem_type_2_id <= 0;			  
	 md_req_op_2_id <= 0;
	 md_req_in_1_signed_2_id <= 0;
	 md_req_in_2_signed_2_id <= 0;
	 md_req_out_sel_2_id <= 0;

	 rs1_2_eq_dst1_id <= 0;
  	 rs2_2_eq_dst1_id <= 0;
	 sptag1_id <= 0;
	 sptag2_id <= 0;
	 tagreg_id <= 0;
//	 spec1_id <= 0;
//	 spec2_id <= 0;
	 inst1_id <= 0;
	 inst2_id <= 0;
	 prcond1_id <= 0;
	 prcond2_id <= 0;
	 inv1_id <= 1;
	 inv2_id <= 1;
	 praddr1_id <= 0;
	 praddr2_id <= 0;
	 pc_id <= 0;
	 bhr_id <= 0;
	 isbranch1_id <= 0;
	 isbranch2_id <= 0;
	 
      end else if (~stall_DP) begin
	 imm_type_1_id <= imm_type_1;
	 rs1_1_id <= rs1_1;
	 rs2_1_id <= rs2_1;
	 rd_1_id <= rd_1;
	 src_a_sel_1_id <= src_a_sel_1;
	 src_b_sel_1_id <= src_b_sel_1;
	 wr_reg_1_id <= wr_reg_1;
	 uses_rs1_1_id <= uses_rs1_1;
	 uses_rs2_1_id <= uses_rs2_1;
	 illegal_instruction_1_id <= illegal_instruction_1;
	 alu_op_1_id <= alu_op_1;
	 rs_ent_1_id <= inv1_if ? 0 : rs_ent_1;
	 dmem_size_1_id <= dmem_size_1;
	 dmem_type_1_id <= dmem_type_1;			  
	 md_req_op_1_id <= md_req_op_1;
	 md_req_in_1_signed_1_id <= md_req_in_1_signed_1;
	 md_req_in_2_signed_1_id <= md_req_in_2_signed_1;
	 md_req_out_sel_1_id <= md_req_out_sel_1;
	 imm_type_2_id <= imm_type_2;
	 rs1_2_id <= rs1_2;
	 rs2_2_id <= rs2_2;
	 rd_2_id <= rd_2;
	 src_a_sel_2_id <= src_a_sel_2;
	 src_b_sel_2_id <= src_b_sel_2;
	 wr_reg_2_id <= wr_reg_2;
	 uses_rs1_2_id <= uses_rs1_2;
	 uses_rs2_2_id <= uses_rs2_2;
	 illegal_instruction_2_id <= illegal_instruction_2;
	 alu_op_2_id <= alu_op_2;
	 rs_ent_2_id <= (inv2_if | (prcond_if & isbranch1)) ? 0 : rs_ent_2;
	 dmem_size_2_id <= dmem_size_2;
	 dmem_type_2_id <= dmem_type_2;			  
	 md_req_op_2_id <= md_req_op_2;
	 md_req_in_1_signed_2_id <= md_req_in_1_signed_2;
	 md_req_in_2_signed_2_id <= md_req_in_2_signed_2;
	 md_req_out_sel_2_id <= md_req_out_sel_2;
	 
	 rs1_2_eq_dst1_id <= (rs1_2 == rd_1 && wr_reg_1) ? 1'b1 : 1'b0;
  	 rs2_2_eq_dst1_id <= (rs2_2 == rd_1 && wr_reg_1) ? 1'b1 : 1'b0;
	 sptag1_id <= sptag1;
	 sptag2_id <= sptag2;
	 tagreg_id <= tagreg;
//	 spec1_id <= spec1;
//	 spec2_id <= spec2;
	 inst1_id <= inst1_if;
	 inst2_id <= inst2_if;
	 prcond1_id <= prcond_if & isbranch1;
	 prcond2_id <= isbranch2 & prcond_if & ~isbranch1;
	 inv1_id <= inv1_if;
	 inv2_id <= inv2_if | (prcond_if & isbranch1);
	 /*
	 praddr1_id <= prcond_if & isbranch1 ? npc_if : pc_if + 4;
	 praddr2_id <= prcond_if & ~isbranch1 & isbranch2 ?
		       npc_if : pc_if + 8;
	  */
	 praddr1_id <= (prcond_if & isbranch1) ? npc_if : (pc_if + 4);
	 praddr2_id <= npc_if;
	 pc_id <= pc_if;
	 bhr_id <= bhr_if;
	 isbranch1_id <= isbranch1;
	 isbranch2_id <= isbranch2;
	 
      end
   end

   //Invalidation of specbit when prsuccess(stall)
   always @ (posedge clk) begin
      if (reset | kill_ID) begin
	 spec1_id <= 0;
	 spec2_id <= 0;
      end else if (prsuccess) begin
	 spec1_id <= (spec1_id && (buf_spectag_branch == sptag1_id)) ?
		     1'b0 : spec1_id;
	 spec2_id <= (spec2_id && (buf_spectag_branch == sptag2_id)) ?
		     1'b0 : spec2_id;
      end else if (~stall_ID) begin
	 spec1_id <= spec1;
	 spec2_id <= spec2;
      end
   end
   
   //DP & SW Stage***************************************************
   assign stall_DP = ~allocatable_alu | ~allocatable_ldst |
		     ~allocatable_mul | ~allocatable_branch | ~alloc_rrf | prsuccess;

   assign kill_DP = prmiss;
   
   
   sourceoperand_manager sopm1_1(
				 .arfdata(adat1_1),
				 .arf_busy(abusy1_1),
				 .rrf_valid(rvalid1_1),
				 .rrftag(rs1_1tag),
				 .rrfdata(rdat1_1),
				 .dst1_renamed(dst1_renamed),
				 .src_eq_dst1(1'b0),
				 .src_eq_0((rs1_1_id == 0) ? 1'b1 : 1'b0),
				 .src(opr1_1),
				 .rdy(rdy1_1)
				 );

   sourceoperand_manager sopm2_1(
				 .arfdata(adat2_1),
				 .arf_busy(abusy2_1),
				 .rrf_valid(rvalid2_1),
				 .rrftag(rs2_1tag),
				 .rrfdata(rdat2_1),
				 .dst1_renamed(dst1_renamed),
				 .src_eq_dst1(1'b0),
				 .src_eq_0((rs2_1_id == 0) ? 1'b1 : 1'b0),
				 .src(opr2_1),
				 .rdy(rdy2_1)
				 );

   sourceoperand_manager sopm1_2(
				 .arfdata(adat1_2),
				 .arf_busy(abusy1_2),
				 .rrf_valid(rvalid1_2),
				 .rrftag(rs1_2tag),
				 .rrfdata(rdat1_2),
				 .dst1_renamed(dst1_renamed),
				 .src_eq_dst1(rs1_2_eq_dst1_id),
				 .src_eq_0((rs1_2_id == 0) ? 1'b1 : 1'b0),
				 .src(opr1_2),
				 .rdy(rdy1_2)
				 );

   sourceoperand_manager sopm2_2(
				 .arfdata(adat2_2),
				 .arf_busy(abusy2_2),
				 .rrf_valid(rvalid2_2),
				 .rrftag(rs2_2tag),
				 .rrfdata(rdat2_2),
				 .dst1_renamed(dst1_renamed),
				 .src_eq_dst1(rs2_2_eq_dst1_id),
				 .src_eq_0((rs2_2_id == 0) ? 1'b1 : 1'b0),
				 .src(opr2_2),
				 .rdy(rdy2_2)
				 );

   
   rrf_freelistmanager rrf_fl(
			      .clk(clk),
			      .reset(reset),
			      .invalid1(inv1_id),
			      .invalid2(inv2_id),
			      .comnum(comnum),
			      .prmiss(prmiss),
			      .rrftagfix(rrftagfix),
			      .rename_dst1(dst1_renamed),
			      .rename_dst2(dst2_renamed),
			      .allocatable(alloc_rrf),
			      .stall_DP(stall_DP),
			      .freenum(freenum),
			      .rrfptr(rrfptr),
			      .comptr(comptr),
			      .nextrrfcyc(nextrrfcyc)
			      );

   arf aregfile(
		.clk(clk),
		.reset(reset),
		.rs1_1(rs1_1_id),
		.rs2_1(rs2_1_id),
		.rs1_2(rs1_2_id),
		.rs2_2(rs2_2_id),
		.rs1_1data(adat1_1),
		.rs2_1data(adat2_1),
		.rs1_2data(adat1_2),
		.rs2_2data(adat2_2),
		.wreg1(dstarf1),
		.wreg2(dstarf2),
		.wdata1(com1data),
		.wdata2(com2data),
		.we1(arfwe1),
		.we2(arfwe2),
		.wrrfent1(comptr),
		.wrrfent2(comptr2),
		.rs1_1tag(rs1_1tag),
		.rs2_1tag(rs2_1tag),
		.rs1_2tag(rs1_2tag),
		.rs2_2tag(rs2_2tag),
		.tagbusy1_addr(rd_1_id),
		.tagbusy2_addr(rd_2_id),
		.tagbusy1_we(~inv1_id & ~stall_DP & wr_reg_1_id),
		.tagbusy2_we(~inv2_id & ~stall_DP & wr_reg_2_id),
		.settag1(dst1_renamed),
		.settag2(dst2_renamed),
		.tagbusy1_spectag(sptag1_id),
		.tagbusy2_spectag(sptag2_id),
		.rs1_1busy(abusy1_1),
		.rs2_1busy(abusy2_1),
		.rs1_2busy(abusy1_2),
		.rs2_2busy(abusy2_2),
		.prmiss(prmiss),
		.prsuccess(prsuccess),
		.prtag(buf_spectag_branch),
//		.mpft_valid1(mpft_valid1_id), //PRsuccess & stall Bug
//		.mpft_valid2(mpft_valid2_id)
		.mpft_valid1(mpft_valid & 
			     (isbranch1_id ? ~sptag1_id : ~(`SPECTAG_LEN'b0)) &
			     (isbranch2_id ? ~sptag2_id : ~(`SPECTAG_LEN'b0))),
		.mpft_valid2(mpft_valid & 
			     (isbranch2_id ? ~sptag2_id : ~(`SPECTAG_LEN'b0)))
		);
   
   assign	rrftagfix = buf_rrftag_branch + 1;
   rrf rregfile(
		.clk(clk),
		.reset(reset),
		.rs1_1tag(rs1_1tag),
		.rs2_1tag(rs2_1tag),
		.rs1_2tag(rs1_2tag),
		.rs2_2tag(rs2_2tag),
		.com1tag(comptr),
		.com2tag(comptr2),
		.rs1_1valid(rvalid1_1),
		.rs2_1valid(rvalid2_1),
		.rs1_2valid(rvalid1_2),
		.rs2_2valid(rvalid2_2),
		.rs1_1data(rdat1_1),
		.rs2_1data(rdat2_1),
		.rs1_2data(rdat1_2),
		.rs2_2data(rdat2_2),
		.com1data(com1data),
		.com2data(com2data),
		.wrrfaddr1(buf_rrftag_alu1),
		.wrrfaddr2(buf_rrftag_alu2),
		.wrrfaddr3(wrrftag_ldst),
		.wrrfaddr4(buf_rrftag_branch),      
		.wrrfaddr5(buf_rrftag_mul),
		.wrrfdata1(result_alu1),
		.wrrfdata2(result_alu2),
		.wrrfdata3(result_ldst),
		.wrrfdata4(result_branch),
		.wrrfdata5(result_mul),
		.wrrfen1(rrfwe_alu1),
		.wrrfen2(rrfwe_alu2),
		.wrrfen3(rrfwe_ldst),
		.wrrfen4(rrfwe_branch),
		.wrrfen5(rrfwe_mul),
		.dpaddr1(dst1_renamed),
		.dpaddr2(dst2_renamed),
		.dpen1(~stall_DP & ~kill_DP & ~inv1_id), // hoge
		.dpen2(~stall_DP & ~kill_DP & ~inv2_id)  // hoge
		);


   src_manager srcmng1_1(
			 .opr(opr1_1),
			 .opr_rdy(rdy1_1),
			 .exrslt1(result_alu1),
			 .exdst1(buf_rrftag_alu1),
			 .kill_spec1(kill_speculative_alu1 | ~robwe_alu1),
			 .exrslt2(result_alu2),
			 .exdst2(buf_rrftag_alu2),
			 .kill_spec2(kill_speculative_alu2 | ~robwe_alu2),
			 .exrslt3(result_ldst),
			 .exdst3(wrrftag_ldst),
			 .kill_spec3(kill_speculative_ldst | ~robwe_ldst),
			 .exrslt4(result_branch),
			 .exdst4(buf_rrftag_branch),
			 .kill_spec4(~robwe_branch),
			 .exrslt5(result_mul),
			 .exdst5(buf_rrftag_mul),
			 .kill_spec5(kill_speculative_mul | ~robwe_mul),
			 .src(src1_1),
			 .resolved(resolved1_1)
			 );

   src_manager srcmng2_1(
			 .opr(opr2_1),
			 .opr_rdy(rdy2_1),
			 .exrslt1(result_alu1),
			 .exdst1(buf_rrftag_alu1),
			 .kill_spec1(kill_speculative_alu1 | ~robwe_alu1),
			 .exrslt2(result_alu2),
			 .exdst2(buf_rrftag_alu2),
			 .kill_spec2(kill_speculative_alu2 | ~robwe_alu2),
			 .exrslt3(result_ldst),
			 .exdst3(wrrftag_ldst),
			 .kill_spec3(kill_speculative_ldst | ~robwe_ldst),
			 .exrslt4(result_branch),
			 .exdst4(buf_rrftag_branch),
			 .kill_spec4(~robwe_branch),
			 .exrslt5(result_mul),
			 .exdst5(buf_rrftag_mul),
			 .kill_spec5(kill_speculative_mul | ~robwe_mul),
			 .src(src2_1),
			 .resolved(resolved2_1)
			 );

   src_manager srcmng1_2(
			 .opr(opr1_2),
			 .opr_rdy(rdy1_2),
			 .exrslt1(result_alu1),
			 .exdst1(buf_rrftag_alu1),
			 .kill_spec1(kill_speculative_alu1 | ~robwe_alu1),
			 .exrslt2(result_alu2),
			 .exdst2(buf_rrftag_alu2),
			 .kill_spec2(kill_speculative_alu2 | ~robwe_alu2),
			 .exrslt3(result_ldst),
			 .exdst3(wrrftag_ldst),
			 .kill_spec3(kill_speculative_ldst | ~robwe_ldst),
			 .exrslt4(result_branch),
			 .exdst4(buf_rrftag_branch),
			 .kill_spec4(~robwe_branch),
			 .exrslt5(result_mul),
			 .exdst5(buf_rrftag_mul),
			 .kill_spec5(kill_speculative_mul | ~robwe_mul),
			 .src(src1_2),
			 .resolved(resolved1_2)
			 );

   src_manager srcmng2_2(
			 .opr(opr2_2),
			 .opr_rdy(rdy2_2),
			 .exrslt1(result_alu1),
			 .exdst1(buf_rrftag_alu1),
			 .kill_spec1(kill_speculative_alu1 | ~robwe_alu1),
			 .exrslt2(result_alu2),
			 .exdst2(buf_rrftag_alu2),
			 .kill_spec2(kill_speculative_alu2 | ~robwe_alu2),
			 .exrslt3(result_ldst),
			 .exdst3(wrrftag_ldst),
			 .kill_spec3(kill_speculative_ldst | ~robwe_ldst),
			 .exrslt4(result_branch),
			 .exdst4(buf_rrftag_branch),
			 .kill_spec4(~robwe_branch),
			 .exrslt5(result_mul),
			 .exdst5(buf_rrftag_mul),
			 .kill_spec5(kill_speculative_mul | ~robwe_mul),
			 .src(src2_2),
			 .resolved(resolved2_2)
			 );

   imm_gen immgen1(
		   .inst(inst1_id),
		   .imm_type(imm_type_1_id),
		   .imm(imm1)
		   );

   imm_gen immgen2(
		   .inst(inst2_id),
		   .imm_type(imm_type_2_id),
		   .imm(imm2)
		   );

   brimm_gen brimmgen1(
		       .inst(inst1_id),
		       .brimm(brimm1)
		       );

   brimm_gen brimmgen2(
		       .inst(inst2_id),
		       .brimm(brimm2)
		       );

   rs_requestgenerator rs_reqgen(
				 .rsent_1(rs_ent_1_id),
				 .rsent_2(rs_ent_2_id),
				 .req1_alu(req1_alu),
				 .req2_alu(req2_alu),
				 .req_alunum(req_alunum),
				 .req1_branch(req1_branch),
				 .req2_branch(req2_branch),
				 .req_branchnum(req_branchnum),
				 .req1_mul(req1_mul),
				 .req2_mul(req2_mul),
				 .req_mulnum(req_mulnum),
				 .req1_ldst(req1_ldst),
				 .req2_ldst(req2_ldst),
				 .req_ldstnum(req_ldstnum)
				 );

   
   //Reservation Station(with Allocate unit, Issue unit)
   //lowest bit of allocent is the selector of RS_alu1/2
   assign 		 rsalu1_we1 = ~allocent1_alu[0];
   assign 		 rsalu1_we2 = req1_alu ? 
			 ~allocent2_alu[0] : ~allocent1_alu[0];
   assign 		 rsalu2_we1 = allocent1_alu[0];
   assign 		 rsalu2_we2 = req1_alu ? 
			 allocent2_alu[0] : allocent1_alu[0];
   
   assign busyvec_alu = 
			{
			 busyvec_alu2[7],busyvec_alu1[7],busyvec_alu2[6],busyvec_alu1[6],
			 busyvec_alu2[5],busyvec_alu1[5],busyvec_alu2[4],busyvec_alu1[4],
			 busyvec_alu2[3],busyvec_alu1[3],busyvec_alu2[2],busyvec_alu1[2],
			 busyvec_alu2[1],busyvec_alu1[1],busyvec_alu2[0],busyvec_alu1[0]
			 };

   assign ready_alu = 
		      {
		       ready_alu2[7],ready_alu1[7],ready_alu2[6],ready_alu1[6],
		       ready_alu2[5],ready_alu1[5],ready_alu2[4],ready_alu1[4],
		       ready_alu2[3],ready_alu1[3],ready_alu2[2],ready_alu1[2],
		       ready_alu2[1],ready_alu1[1],ready_alu2[0],ready_alu1[0]
		       };

   assign 		   issue_alu1 = ~prmiss & issuevalid_alu1;
   assign 		   issue_alu2 = ~prmiss & issuevalid_alu2;
   
   allocateunit #(2*`ALU_ENT_NUM, `ALU_ENT_SEL+1) alloc_alu(
							    .busy(busyvec_alu), //RS_BUSY
							    //      .en1(),
							    //      .en2(),
							    .free_ent1(allocent1_alu),
							    .free_ent2(allocent2_alu),
							    .reqnum(req_alunum),
							    .allocatable(allocatable_alu)
							    );

   /*
    prioenc #(2*`ALU_ENT_NUM, `ALU_ENT_SEL+1) issue_alu
    (
    .in(~ready_alu),
    .out(issueent_alu),
    .en(issuevalid_alu)
    );
    */
/*
   prioenc #(`ALU_ENT_NUM, `ALU_ENT_SEL) isunt_alu1(
						    .in(~ready_alu1),
						    .out(issueentidx_alu1),
						    .en(issuevalid_alu1)
						    );

   prioenc #(`ALU_ENT_NUM, `ALU_ENT_SEL) isunt_alu2(
						    .in(~ready_alu2),
						    .out(issueentidx_alu2),
						    .en(issuevalid_alu2)
						    );
*/
   assign issuevalid_alu1 = ~entval_alu1[`RRF_SEL+1];
   assign issuevalid_alu2 = ~entval_alu2[`RRF_SEL+1];
   
   oldest_finder8 isunt_alu1
     (
      .entvec({`ALU_ENT_SEL'h7, `ALU_ENT_SEL'h6, `ALU_ENT_SEL'h5, `ALU_ENT_SEL'h4,
	       `ALU_ENT_SEL'h3, `ALU_ENT_SEL'h2, `ALU_ENT_SEL'h1, `ALU_ENT_SEL'h0}),
      .valvec(histvect1),
      .oldent(issueent_alu1),
      .oldval(entval_alu1)
      );

   oldest_finder8 isunt_alu2
     (
      .entvec({`ALU_ENT_SEL'h7, `ALU_ENT_SEL'h6, `ALU_ENT_SEL'h5, `ALU_ENT_SEL'h4,
	       `ALU_ENT_SEL'h3, `ALU_ENT_SEL'h2, `ALU_ENT_SEL'h1, `ALU_ENT_SEL'h0}),
      .valvec(histvect2),
      .oldent(issueent_alu2),
      .oldval(entval_alu2)
      );
   
   
   rs_alu reserv_alu1(
		      //System
		      .clk(clk),
		      .reset(reset),
		      .busyvec(busyvec_alu1),
		      .prmiss(prmiss),
		      .prsuccess(prsuccess),
		      .prtag(buf_spectag_branch),
		      .specfixtag(spectagfix),
		      .histvect(histvect1),
		      .nextrrfcyc(nextrrfcyc),
		      //WriteSignal
		      .clearbusy(issue_alu1), //Issue 
		      .issueaddr(issueent_alu1), //= raddr, clsbsyadr
		      .we1(~stall_DP & ~kill_DP & req1_alu & rsalu1_we1), //alloc1
		      .we2(~stall_DP & ~kill_DP & req2_alu & rsalu1_we2), //alloc2
		      .waddr1(allocent1_alu[`ALU_ENT_SEL:1]), //allocent1
		      .waddr2(req1_alu ? 
			      allocent2_alu[`ALU_ENT_SEL:1] : 
			      allocent1_alu[`ALU_ENT_SEL:1]), //allocent2
		      //WriteSignal1
		      .wpc_1(pc_id),
		      .wsrc1_1(src1_1),
		      .wsrc2_1(src2_1),
		      .wvalid1_1(~uses_rs1_1_id | resolved1_1),
		      .wvalid2_1(~uses_rs2_1_id | resolved2_1),
		      .wimm_1(imm1),
		      .wrrftag_1(dst1_renamed),
		      .wdstval_1(wr_reg_1_id),
		      .wsrc_a_1(src_a_sel_1_id),
		      .wsrc_b_1(src_b_sel_1_id),
		      .walu_op_1(alu_op_1_id),
		      .wspectag_1(sptag1_id),
		      .wspecbit_1(spec1_id),
		      //WriteSignal2
		      .wpc_2(pc_id + 4),
		      .wsrc1_2(src1_2),
		      .wsrc2_2(src2_2),
		      .wvalid1_2(~uses_rs1_2_id | resolved1_2),
		      .wvalid2_2(~uses_rs2_2_id | resolved2_2),
		      .wimm_2(imm2),
		      .wrrftag_2(dst2_renamed),
		      .wdstval_2(wr_reg_2_id),
		      .wsrc_a_2(src_a_sel_2_id),
		      .wsrc_b_2(src_b_sel_2_id),
		      .walu_op_2(alu_op_2_id),
		      .wspectag_2(sptag2_id),
		      .wspecbit_2(spec2_id),
		      //ReadSignal
		      .ex_src1(ex_src1_alu1),
		      .ex_src2(ex_src2_alu1),
		      .ready(ready_alu1),
		      .pc(pc_alu1),
		      .imm(imm_alu1),
		      .rrftag(rrftag_alu1),
		      .dstval(dstval_alu1),
		      .src_a(src_a_alu1),
		      .src_b(src_b_alu1),
		      .alu_op(alu_op_alu1),
		      .spectag(spectag_alu1),
		      .specbit(specbit_alu1),
		      //EXRSLT
		      .exrslt1(result_alu1),
		      .exdst1(buf_rrftag_alu1),
		      .kill_spec1(kill_speculative_alu1 | ~robwe_alu1),
		      .exrslt2(result_alu2),
		      .exdst2(buf_rrftag_alu2),
		      .kill_spec2(kill_speculative_alu2 | ~robwe_alu2),
		      .exrslt3(result_ldst),
		      .exdst3(wrrftag_ldst),
		      .kill_spec3(kill_speculative_ldst | ~robwe_ldst),
		      .exrslt4(result_branch),
		      .exdst4(buf_rrftag_branch),
		      .kill_spec4(~robwe_branch),
		      .exrslt5(result_mul),
		      .exdst5(buf_rrftag_mul),
		      .kill_spec5(kill_speculative_mul | ~robwe_mul)
		      );

   rs_alu reserv_alu2(
		      //System
		      .clk(clk),
		      .reset(reset),
		      .busyvec(busyvec_alu2),
		      .prmiss(prmiss),
		      .prsuccess(prsuccess),
		      .prtag(buf_spectag_branch),
		      .specfixtag(spectagfix),
		      .histvect(histvect2),
		      .nextrrfcyc(nextrrfcyc),
		      //WriteSignal
		      .clearbusy(issue_alu2), //Issue 
		      .issueaddr(issueent_alu2), //= raddr, clsbsyadr
		      .we1(~stall_DP & ~kill_DP & req1_alu & rsalu2_we1), //alloc1
		      .we2(~stall_DP & ~kill_DP & req2_alu & rsalu2_we2), //alloc2
		      .waddr1(allocent1_alu[`ALU_ENT_SEL:1]), //allocent1
		      .waddr2(req1_alu ? 
			      allocent2_alu[`ALU_ENT_SEL:1] : 
			      allocent1_alu[`ALU_ENT_SEL:1]), //allocent2
		      //WriteSignal1
		      .wpc_1(pc_id),
		      .wsrc1_1(src1_1),
		      .wsrc2_1(src2_1),
		      .wvalid1_1(~uses_rs1_1_id | resolved1_1),
		      .wvalid2_1(~uses_rs2_1_id | resolved2_1),
		      .wimm_1(imm1),
		      .wrrftag_1(dst1_renamed),
		      .wdstval_1(wr_reg_1_id),
		      .wsrc_a_1(src_a_sel_1_id),
		      .wsrc_b_1(src_b_sel_1_id),
		      .walu_op_1(alu_op_1_id),
		      .wspectag_1(sptag1_id),
		      .wspecbit_1(spec1_id),
		      //WriteSignal2
		      .wpc_2(pc_id + 4),
		      .wsrc1_2(src1_2),
		      .wsrc2_2(src2_2),
		      .wvalid1_2(~uses_rs1_2_id | resolved1_2),
		      .wvalid2_2(~uses_rs2_2_id | resolved2_2),
		      .wimm_2(imm2),
		      .wrrftag_2(dst2_renamed),
		      .wdstval_2(wr_reg_2_id),
		      .wsrc_a_2(src_a_sel_2_id),
		      .wsrc_b_2(src_b_sel_2_id),
		      .walu_op_2(alu_op_2_id),
		      .wspectag_2(sptag2_id),
		      .wspecbit_2(spec2_id),
		      //ReadSignal
		      .ex_src1(ex_src1_alu2),
		      .ex_src2(ex_src2_alu2),
		      .ready(ready_alu2),
		      .pc(pc_alu2),
		      .imm(imm_alu2),
		      .rrftag(rrftag_alu2),
		      .dstval(dstval_alu2),
		      .src_a(src_a_alu2),
		      .src_b(src_b_alu2),
		      .alu_op(alu_op_alu2),
		      .spectag(spectag_alu2),
		      .specbit(specbit_alu2),
		      //EXRSLT
		      .exrslt1(result_alu1),
		      .exdst1(buf_rrftag_alu1),
		      .kill_spec1(kill_speculative_alu1 | ~robwe_alu1),
		      .exrslt2(result_alu2),
		      .exdst2(buf_rrftag_alu2),
		      .kill_spec2(kill_speculative_alu2 | ~robwe_alu2),
		      .exrslt3(result_ldst),
		      .exdst3(wrrftag_ldst),
		      .kill_spec3(kill_speculative_ldst | ~robwe_ldst),
		      .exrslt4(result_branch),
		      .exdst4(buf_rrftag_branch),
		      .kill_spec4(~robwe_branch),
		      .exrslt5(result_mul),
		      .exdst5(buf_rrftag_mul),
		      .kill_spec5(kill_speculative_mul | ~robwe_mul)
		      );


   assign allocent2_ldst = allocent1_ldst + 1;
   assign issue_ldst = ~prmiss & issuevalid_ldst;

   alloc_issue_ino #(`LDST_ENT_SEL, `LDST_ENT_NUM) ai_ldst
     (
      .clk(clk),
      .reset(reset),
      .reqnum(req_ldstnum),
      .busyvec(busyvec_ldst),
      .prbusyvec_next(prbusyvec_next_ldst),
      .readyvec(ready_ldst),
      .prmiss(prmiss),
      .exunit_busynext(busy_next_ldst),
      .stall_DP(stall_DP),
      .kill_DP(kill_DP),
      .allocptr(allocent1_ldst),
      .allocatable(allocatable_ldst),
      .issueptr(issueent_ldst),
      .issuevalid(issuevalid_ldst)
      );
   
   rs_ldst reserv_ldst(
		       //System
		       .clk(clk),
		       .reset(reset),
		       .busyvec(busyvec_ldst),
		       .prmiss(prmiss),
		       .prsuccess(prsuccess),
		       .prtag(buf_spectag_branch),
		       .specfixtag(spectagfix),
		       .prbusyvec_next(prbusyvec_next_ldst),
		       //WriteSignal
		       .clearbusy(issue_ldst), //Issue 
		       .issueaddr(issueent_ldst), //= raddr, clsbsyadr
		       .we1(~stall_DP & ~kill_DP & req1_ldst), //alloc1
		       .we2(~stall_DP & ~kill_DP & req2_ldst), //alloc2
		       .waddr1(allocent1_ldst), //allocent1
		       .waddr2(req1_ldst ? 
			       allocent2_ldst : allocent1_ldst), //allocent2
		       //WriteSignal1
		       .wpc_1(pc_id),
		       .wsrc1_1(src1_1),
		       .wsrc2_1(src2_1),
		       .wvalid1_1(~uses_rs1_1_id | resolved1_1),
		       .wvalid2_1(~uses_rs2_1_id | resolved2_1),
		       .wimm_1(imm1),
		       .wrrftag_1(dst1_renamed),
		       .wdstval_1(wr_reg_1_id),
		       .wspectag_1(sptag1_id),
		       .wspecbit_1(spec1_id),
		       //WriteSignal2
		       .wpc_2(pc_id + 4),
		       .wsrc1_2(src1_2),
		       .wsrc2_2(src2_2),
		       .wvalid1_2(~uses_rs1_2_id | resolved1_2),
		       .wvalid2_2(~uses_rs2_2_id | resolved2_2),
		       .wimm_2(imm2),
		       .wrrftag_2(dst2_renamed),
		       .wdstval_2(wr_reg_2_id),
		       .wspectag_2(sptag2_id),
		       .wspecbit_2(spec2_id),
		       //ReadSignal
		       .ex_src1(ex_src1_ldst),
		       .ex_src2(ex_src2_ldst),
		       .ready(ready_ldst),
		       .pc(pc_ldst),
		       .imm(imm_ldst),
		       .rrftag(rrftag_ldst),
		       .dstval(dstval_ldst),
		       .spectag(spectag_ldst),
		       .specbit(specbit_ldst),
		       //EXRSLT
		       .exrslt1(result_alu1),
		       .exdst1(buf_rrftag_alu1),
		       .kill_spec1(kill_speculative_alu1 | ~robwe_alu1),
		       .exrslt2(result_alu2),
		       .exdst2(buf_rrftag_alu2),
		       .kill_spec2(kill_speculative_alu2 | ~robwe_alu2),
		       .exrslt3(result_ldst),
		       .exdst3(wrrftag_ldst),
		       .kill_spec3(kill_speculative_ldst | ~robwe_ldst),
		       .exrslt4(result_branch),
		       .exdst4(buf_rrftag_branch),
		       .kill_spec4(~robwe_branch),
		       .exrslt5(result_mul),
		       .exdst5(buf_rrftag_mul),
		       .kill_spec5(kill_speculative_mul | ~robwe_mul)
		       );


   assign allocent2_branch = allocent1_branch + 1;
   assign issue_branch = ~prmiss & issuevalid_branch;
   
   alloc_issue_ino ai_branch(
			     .clk(clk),
			     .reset(reset),
			     .reqnum(req_branchnum),
			     .busyvec(busyvec_branch),
			     .prbusyvec_next(prbusyvec_next_branch),
			     .readyvec(ready_branch),
			     .prmiss(prmiss),
			     .exunit_busynext(1'b0),
			     .stall_DP(stall_DP),
			     .kill_DP(kill_DP),
			     .allocptr(allocent1_branch),
			     .allocatable(allocatable_branch),
			     .issueptr(issueent_branch),
			     .issuevalid(issuevalid_branch)
			     );
   
   rs_branch reserv_branch(
			   //System
			   .clk(clk),
			   .reset(reset),
			   .busyvec(busyvec_branch),
			   .prmiss(prmiss),
			   .prsuccess(prsuccess),
			   .prtag(buf_spectag_branch),
			   .specfixtag(spectagfix),
			   .prbusyvec_next(prbusyvec_next_branch),
			   //WriteSignal
			   .clearbusy(issue_branch), //Issue 
			   .issueaddr(issueent_branch), //= raddr, clsbsyadr
			   .we1(~stall_DP & ~kill_DP & req1_branch), //alloc1
			   .we2(~stall_DP & ~kill_DP & req2_branch), //alloc2
			   .waddr1(allocent1_branch), //allocent1
			   .waddr2(req1_branch ? 
				   allocent2_branch : allocent1_branch), //allocent2
			   //WriteSignal1
			   .wpc_1(pc_id),
			   .wsrc1_1(src1_1),
			   .wsrc2_1(src2_1),
			   .wvalid1_1(~uses_rs1_1_id | resolved1_1),
			   .wvalid2_1(~uses_rs2_1_id | resolved2_1),
			   .wimm_1(brimm1),
			   .wrrftag_1(dst1_renamed),
			   .wdstval_1(wr_reg_1_id),
			   .walu_op_1(alu_op_1_id),
			   .wspectag_1(sptag1_id),
			   .wspecbit_1(spec1_id),
			   .wbhr_1(bhr_id),
			   .wprcond_1(prcond1_id),
			   .wpraddr_1(praddr1_id),
			   .wopcode_1(inst1_id[6:0]),
			   //WriteSignal2
			   .wpc_2(pc_id + 4),
			   .wsrc1_2(src1_2),
			   .wsrc2_2(src2_2),
			   .wvalid1_2(~uses_rs1_2_id | resolved1_2),
			   .wvalid2_2(~uses_rs2_2_id | resolved2_2),
			   .wimm_2(brimm2),
			   .wrrftag_2(dst2_renamed),
			   .wdstval_2(wr_reg_2_id),
			   .walu_op_2(alu_op_2_id),
			   .wspectag_2(sptag2_id),
			   .wspecbit_2(spec2_id),
			   .wbhr_2(bhr_id),
			   .wprcond_2(prcond2_id),
			   .wpraddr_2(praddr2_id),
			   .wopcode_2(inst2_id[6:0]),
			   //ReadSignal
			   .ex_src1(ex_src1_branch),
			   .ex_src2(ex_src2_branch),
			   .ready(ready_branch),
			   .pc(pc_branch),
			   .imm(imm_branch),
			   .rrftag(rrftag_branch),
			   .dstval(dstval_branch),
			   .alu_op(alu_op_branch),
			   .spectag(spectag_branch),
			   .specbit(specbit_branch),
			   .bhr(bhr_branch),
			   .prcond(prcond_branch),
			   .praddr(praddr_branch),
			   .opcode(opcode_branch),
			   //EXRSLT
			   .exrslt1(result_alu1),
			   .exdst1(buf_rrftag_alu1),
			   .kill_spec1(kill_speculative_alu1 | ~robwe_alu1),
			   .exrslt2(result_alu2),
			   .exdst2(buf_rrftag_alu2),
			   .kill_spec2(kill_speculative_alu2 | ~robwe_alu2),
			   .exrslt3(result_ldst),
			   .exdst3(wrrftag_ldst),
			   .kill_spec3(kill_speculative_ldst | ~robwe_ldst),
			   .exrslt4(result_branch),
			   .exdst4(buf_rrftag_branch),
			   .kill_spec4(~robwe_branch),
			   .exrslt5(result_mul),
			   .exdst5(buf_rrftag_mul),
			   .kill_spec5(kill_speculative_mul | ~robwe_mul)
			   );

   assign issue_mul = ~prmiss & issuevalid_mul;

   allocateunit #(`MUL_ENT_NUM, `MUL_ENT_SEL) alloc_mul(
							.busy(busyvec_mul), //RS_BUSY
							//      .en1(),
							//      .en2(),
							.free_ent1(allocent1_mul),
							.free_ent2(allocent2_mul),
							.reqnum(req_mulnum),
							.allocatable(allocatable_mul)
							);

   prioenc #(`MUL_ENT_NUM, `MUL_ENT_SEL) isunt_mul(
						   .in(~ready_mul),
						   .out(issueent_mul),
						   .en(issuevalid_mul)
						   );
   
   rs_mul reserv_mul(
		     //System
		     .clk(clk),
		     .reset(reset),
		     .busyvec(busyvec_mul),
		     .prmiss(prmiss),
		     .prsuccess(prsuccess),
		     .prtag(buf_spectag_branch),
		     .specfixtag(spectagfix),
		     //WriteSignal
		     .clearbusy(issue_mul), //Issue 
		     .issueaddr(issueent_mul), //= raddr, clsbsyadr
		     .we1(~stall_DP & ~kill_DP & req1_mul), //alloc1
		     .we2(~stall_DP & ~kill_DP & req2_mul), //alloc2
		     .waddr1(allocent1_mul), //allocent1
		     .waddr2(req1_mul ? 
			     allocent2_mul : allocent1_mul), //allocent2
		     //WriteSignal1
		     .wsrc1_1(src1_1),
		     .wsrc2_1(src2_1),
		     .wvalid1_1(~uses_rs1_1_id | resolved1_1),
		     .wvalid2_1(~uses_rs2_1_id | resolved2_1),
		     .wrrftag_1(dst1_renamed),
		     .wdstval_1(wr_reg_1_id),
		     .wspectag_1(sptag1_id),
		     .wspecbit_1(spec1_id),
		     .wsrc1_signed_1(md_req_in_1_signed_1_id),
		     .wsrc2_signed_1(md_req_in_2_signed_1_id),
		     .wsel_lohi_1(md_req_out_sel_1_id[0]),
		     //WriteSignal2
		     .wsrc1_2(src1_2),
		     .wsrc2_2(src2_2),
		     .wvalid1_2(~uses_rs1_2_id | resolved1_2),
		     .wvalid2_2(~uses_rs2_2_id | resolved2_2),
		     .wrrftag_2(dst2_renamed),
		     .wdstval_2(wr_reg_2_id),
		     .wspectag_2(sptag2_id),
		     .wspecbit_2(spec2_id),
		     .wsrc1_signed_2(md_req_in_1_signed_2_id),
		     .wsrc2_signed_2(md_req_in_2_signed_2_id),
		     .wsel_lohi_2(md_req_out_sel_2_id[0]),
		     //ReadSignal
		     .ex_src1(ex_src1_mul),
		     .ex_src2(ex_src2_mul),
		     .ready(ready_mul),
		     .rrftag(rrftag_mul),
		     .dstval(dstval_mul),
		     .spectag(spectag_mul),
		     .specbit(specbit_mul),
		     .src1_signed(src1_signed_mul),
		     .src2_signed(src2_signed_mul),
		     .sel_lohi(sel_lohi_mul),
		     //EXRSLT
		     .exrslt1(result_alu1),
		     .exdst1(buf_rrftag_alu1),
		     .kill_spec1(kill_speculative_alu1 | ~robwe_alu1),
		     .exrslt2(result_alu2),
		     .exdst2(buf_rrftag_alu2),
		     .kill_spec2(kill_speculative_alu2 | ~robwe_alu2),
		     .exrslt3(result_ldst),
		     .exdst3(wrrftag_ldst),
		     .kill_spec3(kill_speculative_ldst | ~robwe_ldst),
		     .exrslt4(result_branch),
		     .exdst4(buf_rrftag_branch),
		     .kill_spec4(~robwe_branch),
		     .exrslt5(result_mul),
		     .exdst5(buf_rrftag_mul),
		     .kill_spec5(kill_speculative_mul | ~robwe_mul)
		     );
   
   //EX Stage********************************************************

   always @ (posedge clk) begin
      if (reset) begin
	 buf_ex_src1_alu1 <= 0;
	 buf_ex_src2_alu1 <= 0;
	 buf_pc_alu1 <= 0;
	 buf_imm_alu1 <= 0;
	 buf_rrftag_alu1 <= 0;
	 buf_dstval_alu1 <= 0;
	 buf_src_a_alu1 <= 0;
	 buf_src_b_alu1 <= 0;
	 buf_alu_op_alu1 <= 0;
	 buf_spectag_alu1 <= 0;
	 buf_specbit_alu1 <= 0;
      end else if (issue_alu1) begin
	 buf_ex_src1_alu1 <= ex_src1_alu1;
	 buf_ex_src2_alu1 <= ex_src2_alu1;
	 buf_pc_alu1 <= pc_alu1;
	 buf_imm_alu1 <= imm_alu1;
	 buf_rrftag_alu1 <= rrftag_alu1;
	 buf_dstval_alu1 <= dstval_alu1;
	 buf_src_a_alu1 <= src_a_alu1;
	 buf_src_b_alu1 <= src_b_alu1;
	 buf_alu_op_alu1 <= alu_op_alu1;
	 buf_spectag_alu1 <= spectag_alu1;
	 buf_specbit_alu1 <= specbit_alu1;
      end
   end
   
   exunit_alu byakko(
		     .clk(clk),
		     .reset(reset),
		     .ex_src1(buf_ex_src1_alu1),
		     .ex_src2(buf_ex_src2_alu1),
		     .pc(buf_pc_alu1),
		     .imm(buf_imm_alu1),
		     .dstval(buf_dstval_alu1),
		     .src_a(buf_src_a_alu1),
		     .src_b(buf_src_b_alu1),
		     .alu_op(buf_alu_op_alu1),
		     .spectag(buf_spectag_alu1),
		     .specbit(buf_specbit_alu1),
		     .issue(issue_alu1),
		     .prmiss(prmiss),
		     .spectagfix(spectagfix),
		     .result(result_alu1),
		     .rrf_we(rrfwe_alu1),
		     .rob_we(robwe_alu1),
		     .kill_speculative(kill_speculative_alu1)
		     );

   always @ (posedge clk) begin
      if (reset) begin
	 buf_ex_src1_alu2 <= 0;
	 buf_ex_src2_alu2 <= 0;
	 buf_pc_alu2 <= 0;
	 buf_imm_alu2 <= 0;
	 buf_rrftag_alu2 <= 0;
	 buf_dstval_alu2 <= 0;
	 buf_src_a_alu2 <= 0;
	 buf_src_b_alu2 <= 0;
	 buf_alu_op_alu2 <= 0;
	 buf_spectag_alu2 <= 0;
	 buf_specbit_alu2 <= 0;
      end else if (issue_alu2) begin
	 buf_ex_src1_alu2 <= ex_src1_alu2;
	 buf_ex_src2_alu2 <= ex_src2_alu2;
	 buf_pc_alu2 <= pc_alu2;
	 buf_imm_alu2 <= imm_alu2;
	 buf_rrftag_alu2 <= rrftag_alu2;
	 buf_dstval_alu2 <= dstval_alu2;
	 buf_src_a_alu2 <= src_a_alu2;
	 buf_src_b_alu2 <= src_b_alu2;
	 buf_alu_op_alu2 <= alu_op_alu2;
	 buf_spectag_alu2 <= spectag_alu2;
	 buf_specbit_alu2 <= specbit_alu2;
      end
   end
   
   exunit_alu suzaku(
		     .clk(clk),
		     .reset(reset),
		     .ex_src1(buf_ex_src1_alu2),
		     .ex_src2(buf_ex_src2_alu2),
		     .pc(buf_pc_alu2),
		     .imm(buf_imm_alu2),
		     .dstval(buf_dstval_alu2),
		     .src_a(buf_src_a_alu2),
		     .src_b(buf_src_b_alu2),
		     .alu_op(buf_alu_op_alu2),
		     .spectag(buf_spectag_alu2),
		     .specbit(buf_specbit_alu2),
		     .issue(issue_alu2),
		     .prmiss(prmiss),
		     .spectagfix(spectagfix),
		     .result(result_alu2),
		     .rrf_we(rrfwe_alu2),
		     .rob_we(robwe_alu2),
		     .kill_speculative(kill_speculative_alu2)
		     );

   always @ (posedge clk) begin
      if (reset) begin
	 buf_ex_src1_ldst <= 0;
	 buf_ex_src2_ldst <= 0;
	 buf_pc_ldst <= 0;
	 buf_imm_ldst <= 0;
	 buf_rrftag_ldst <= 0;
	 buf_dstval_ldst <= 0;
	 buf_spectag_ldst <= 0;
	 buf_specbit_ldst <= 0;
      end else if (issue_ldst) begin
	 buf_ex_src1_ldst <= ex_src1_ldst;
	 buf_ex_src2_ldst <= ex_src2_ldst;
	 buf_pc_ldst <= pc_ldst;
	 buf_imm_ldst <= imm_ldst;
	 buf_rrftag_ldst <= rrftag_ldst;
	 buf_dstval_ldst <= dstval_ldst;
	 buf_spectag_ldst <= spectag_ldst;
	 buf_specbit_ldst <= specbit_ldst;
      end
   end // always @ (posedge clk)

   assign dmem_addr = (memoccupy_ld) ? ldaddr : retaddr;

/*   
   dmem datamemory(
		   .clk(clk),
		   .addr({2'b0, dmem_addr[`ADDR_LEN-1:2]}),
		   .wdata(dmem_wdata),
		   .we(dmem_we),
		   .rdata(dmem_data)
		   );
*/
   storebuf sb
     (
      .clk(clk),
      .reset(reset),
      .prsuccess(prsuccess),
      .prmiss(prmiss),
      .prtag(buf_spectag_branch),
      .spectagfix(spectagfix),
      .stfin(stfin),
      .stspecbit(buf_specbit_ldst),
      .stspectag(buf_spectag_ldst),
      .stdata(storedata),
      .staddr(storeaddr),
      .stcom(stcommit),
      .stretire(dmem_we),
      .retdata(dmem_wdata),
      .retaddr(retaddr),
      .memoccupy_ld(memoccupy_ld),
      .sb_full(sb_full),
      .ldaddr(ldaddr),
      .lddata(lddatasb),
      .hit(hitsb)
      );

   exunit_ldst seiryu(
		      .clk(clk),
		      .reset(reset),
		      .ex_src1(buf_ex_src1_ldst),
		      .ex_src2(buf_ex_src2_ldst),
		      .pc(buf_pc_ldst),
		      .imm(buf_imm_ldst),
		      .dstval(buf_dstval_ldst),
		      .spectag(buf_spectag_ldst),
		      .specbit(buf_specbit_ldst),
		      .rrftag(buf_rrftag_ldst),
		      .issue(issue_ldst),
		      .prmiss(prmiss),
		      .spectagfix(spectagfix),
		      .result(result_ldst),
		      .rrf_we(rrfwe_ldst),
		      .rob_we(robwe_ldst),
		      .wrrftag(wrrftag_ldst),
		      .kill_speculative(kill_speculative_ldst),
		      .busy_next(busy_next_ldst),
		      .stfin(stfin),
		      .memoccupy_ld(memoccupy_ld),
		      .fullsb(sb_full),
		      .storedata(storedata),
		      .storeaddr(storeaddr),
		      .hitsb(hitsb),
		      .ldaddr(ldaddr),
		      .lddatasb(lddatasb),
		      .lddatamem(dmem_data)
		      );

   always @ (posedge clk) begin
      if (reset) begin
	 buf_ex_src1_mul <= 0;
	 buf_ex_src2_mul <= 0;
	 buf_pc_mul <= 0;
	 buf_rrftag_mul <= 0;
	 buf_dstval_mul <= 0;
	 buf_spectag_mul <= 0;
	 buf_specbit_mul <= 0;
	 buf_src1_signed_mul <= 0;
	 buf_src2_signed_mul <= 0;
	 buf_sel_lohi_mul <= 0;
      end else if (issue_mul) begin
	 buf_ex_src1_mul <= ex_src1_mul;
	 buf_ex_src2_mul <= ex_src2_mul;
	 buf_pc_mul <= pc_mul;
	 buf_rrftag_mul <= rrftag_mul;
	 buf_dstval_mul <= dstval_mul;
	 buf_spectag_mul <= spectag_mul;
	 buf_specbit_mul <= specbit_mul;
	 buf_src1_signed_mul <= src1_signed_mul;
	 buf_src2_signed_mul <= src2_signed_mul;
	 buf_sel_lohi_mul <= sel_lohi_mul;
      end
   end
   
   exunit_mul genbu (
		     .clk(clk),
		     .reset(reset),
		     .ex_src1(buf_ex_src1_mul),
		     .ex_src2(buf_ex_src2_mul),
		     .dstval(buf_dstval_mul),
		     .spectag(buf_spectag_mul),
		     .specbit(buf_specbit_mul),
		     .src1_signed(buf_src1_signed_mul),
		     .src2_signed(buf_src2_signed_mul),
		     .sel_lohi(buf_sel_lohi_mul),
		     .issue(issue_mul),
		     .prmiss(prmiss),
		     .spectagfix(spectagfix),
		     .result(result_mul),
		     .rrf_we(rrfwe_mul),
		     .rob_we(robwe_mul),
		     .kill_speculative(kill_speculative_mul)
		     );


   always @ (posedge clk) begin
      if (reset) begin
	 buf_ex_src1_branch <= 0;
	 buf_ex_src2_branch <= 0;
	 buf_pc_branch <= 0;
	 buf_imm_branch <= 0;
	 buf_rrftag_branch <= 0;
	 buf_dstval_branch <= 0;
	 buf_alu_op_branch <= 0;
	 buf_spectag_branch <= 0;
	 buf_specbit_branch <= 0;
	 buf_praddr_branch <= 0;
	 buf_opcode_branch <= 0;
      end else if (issue_branch) begin
	 buf_ex_src1_branch <= ex_src1_branch;
	 buf_ex_src2_branch <= ex_src2_branch;
	 buf_pc_branch <= pc_branch;
	 buf_imm_branch <= imm_branch;
	 buf_rrftag_branch <= rrftag_branch;
	 buf_dstval_branch <= dstval_branch;
	 buf_alu_op_branch <= alu_op_branch;
	 buf_spectag_branch <= spectag_branch;
	 buf_specbit_branch <= specbit_branch;
	 buf_praddr_branch <= praddr_branch;
	 buf_opcode_branch <= opcode_branch;
      end
   end
   
   exunit_branch kirin(
		       .clk(clk),
		       .reset(reset),
		       .ex_src1(buf_ex_src1_branch),
		       .ex_src2(buf_ex_src2_branch),
		       .pc(buf_pc_branch),
		       .imm(buf_imm_branch),
		       .dstval(buf_dstval_branch),
		       .alu_op(buf_alu_op_branch),
		       .spectag(buf_spectag_branch),
		       .specbit(buf_specbit_branch),
		       .praddr(buf_praddr_branch),
		       .opcode(buf_opcode_branch),
		       .issue(issue_branch),
		       .result(result_branch),
		       .rrf_we(rrfwe_branch),
		       .rob_we(robwe_branch),
		       .prsuccess(prsuccess),
		       .prmiss(prmiss),
		       .jmpaddr(jmpaddr),
		       .jmpaddr_taken(jmpaddr_taken),
		       .brcond(brcond),
		       .tagregfix(tagregfix)
		       );

   
   miss_prediction_fix_table mpft(
				  .clk(clk),
				  .reset(reset),
				  .mpft_valid(mpft_valid),
				  .value_addr(buf_spectag_branch),
				  .mpft_value(spectagfix),
				  .prmiss(prmiss),
				  .prsuccess(prsuccess),
				  .prsuccess_tag(buf_spectag_branch),
				  .setspec1_tag(sptag1),
				  .setspec1_en(isbranch1 & ~stall_ID & ~stall_DP),
				  .setspec2_tag(sptag2),
				  .setspec2_en(branchvalid2 & ~stall_ID & ~stall_DP)
				  );
   
   //COM Stage*******************************************************
   reorderbuf rob(
		  .clk(clk),
		  .reset(reset),
		  .dp1(~stall_DP & ~kill_DP & ~inv1_id),
		  .dp1_addr(dst1_renamed),
		  .pc_dp1(pc_id),
		  .storebit_dp1(inst1_id[6:0] == `RV32_STORE ? 1'b1 : 1'b0),
		  .dstvalid_dp1(wr_reg_1_id),
		  .dst_dp1(rd_1_id),
		  .bhr_dp1(bhr_id),
		  .isbranch_dp1(req1_branch),
		  .dp2(~stall_DP & ~kill_DP & ~inv2_id),
		  .dp2_addr(dst2_renamed),
		  .pc_dp2(pc_id + 4),
		  .storebit_dp2(inst2_id[6:0] == `RV32_STORE ? 1'b1 : 1'b0),
		  .dstvalid_dp2(wr_reg_2_id),
		  .dst_dp2(rd_2_id),
		  .bhr_dp2(bhr_id),
		  .isbranch_dp2(req2_branch),
		  .exfin_alu1(robwe_alu1),
		  .exfin_alu1_addr(buf_rrftag_alu1),
		  .exfin_alu2(robwe_alu2),
		  .exfin_alu2_addr(buf_rrftag_alu2),
		  .exfin_mul(robwe_mul),
		  .exfin_mul_addr(buf_rrftag_mul),
		  .exfin_ldst(robwe_ldst),
		  .exfin_ldst_addr(wrrftag_ldst),
		  .exfin_branch(robwe_branch),
		  .exfin_branch_addr(buf_rrftag_branch),
		  .exfin_branch_brcond(brcond),
		  .exfin_branch_jmpaddr(jmpaddr_taken),

		  .comptr(comptr),
		  .comptr2(comptr2),
		  .comnum(comnum),
		  .stcommit(stcommit),
		  .arfwe1(arfwe1),
		  .arfwe2(arfwe2),
		  .dstarf1(dstarf1),
		  .dstarf2(dstarf2),
		  .pc_combranch(pc_combranch),
		  .bhr_combranch(bhr_combranch),
		  .brcond_combranch(brcond_combranch),
		  .jmpaddr_combranch(jmpaddr_combranch),
		  .combranch(combranch),
		  .dispatchptr(rrfptr),
		  .rrf_freenum(freenum),
		  .prmiss(prmiss)
		  );
   
endmodule // pipeline

`default_nettype wire
`default_nettype none
module prioenc #(
		 parameter REQ_LEN = 4,
		 parameter GRANT_LEN = 2
		 )
   (
    input wire [REQ_LEN-1:0]   in,
    output reg [GRANT_LEN-1:0] out,
    output reg 		       en
   );
   
   integer 		      i;
   always @ (*) begin
      en = 0;
      out = 0;
      for (i = REQ_LEN-1 ; i >= 0 ; i = i - 1) begin
	 if (~in[i]) begin
	    out = i;
	    en = 1;
	 end
      end
   end
endmodule

module maskunit  #(
		   parameter REQ_LEN = 4,
		   parameter GRANT_LEN = 2
		   )
   (
    input wire [GRANT_LEN-1:0] mask,
    input wire [REQ_LEN-1:0]   in,
    output reg [REQ_LEN-1:0]   out
   );
   
   integer 		      i;
   always @ (*) begin
      out = 0;
      for (i = 0 ; i < REQ_LEN ; i = i+1) begin
	 out[i] = (mask < i) ? 1'b0 : 1'b1;
      end
   end
endmodule

module allocateunit  #(
		       parameter REQ_LEN = 4,
		       parameter GRANT_LEN = 2
		       )
   (
    input wire [REQ_LEN-1:0] 	busy,
    output wire 		en1,
    output wire 		en2,
    output wire [GRANT_LEN-1:0] free_ent1,
    output wire [GRANT_LEN-1:0] free_ent2,
    input wire [1:0] 		reqnum,
    output wire 		allocatable
   );
   
   wire [REQ_LEN-1:0] 	       busy_msk;
   
   prioenc #(REQ_LEN, GRANT_LEN) p1
     (
      .in(busy),
      .out(free_ent1),
      .en(en1)
      );

   maskunit #(REQ_LEN, GRANT_LEN) msku
     (
      .mask(free_ent1),
      .in(busy),
      .out(busy_msk)
      );
   
   prioenc #(REQ_LEN, GRANT_LEN) p2
     (
      .in(busy | busy_msk),
      .out(free_ent2),
      .en(en2)
      );

   assign allocatable = (reqnum > ({1'b0,en1}+{1'b0,en2})) ? 1'b0 : 1'b1;
endmodule
`default_nettype wire
`include "constants.vh"
`default_nettype none
module ram_sync_nolatch_2r1w #(
			       parameter BRAM_ADDR_WIDTH = `ADDR_LEN,
			       parameter BRAM_DATA_WIDTH = `DATA_LEN,
			       parameter DATA_DEPTH      = 32
			       ) 
   (
    input wire 			      clk,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr1,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr2,
    output wire [BRAM_DATA_WIDTH-1:0] rdata1,
    output wire [BRAM_DATA_WIDTH-1:0] rdata2,
    input wire [BRAM_ADDR_WIDTH-1:0]  waddr,
    input wire [BRAM_DATA_WIDTH-1:0]  wdata,
    input wire 			      we
    );
   
   reg [BRAM_DATA_WIDTH-1:0] 				       mem [0:DATA_DEPTH-1];

   integer 						       i;
   
   assign rdata1 = mem[raddr1];
   assign rdata2 = mem[raddr2];
   
   always @ (posedge clk) begin
      if (we)
	mem[waddr] <= wdata;
   end
endmodule // ram_sync_nolatch_2r1w

module ram_sync_nolatch_2r2w #(
			       parameter BRAM_ADDR_WIDTH = `ADDR_LEN,
			       parameter BRAM_DATA_WIDTH = `DATA_LEN,
			       parameter DATA_DEPTH      = 32
			       ) 
   (
    input wire 			      clk,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr1,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr2,
    output wire [BRAM_DATA_WIDTH-1:0] rdata1,
    output wire [BRAM_DATA_WIDTH-1:0] rdata2,
    input wire [BRAM_ADDR_WIDTH-1:0]  waddr1,
    input wire [BRAM_ADDR_WIDTH-1:0]  waddr2,
    input wire [BRAM_DATA_WIDTH-1:0]  wdata1,
    input wire [BRAM_DATA_WIDTH-1:0]  wdata2,
    input wire 			      we1,
    input wire 			      we2
    );
   
   reg [BRAM_DATA_WIDTH-1:0] 				       mem [0:DATA_DEPTH-1];

   assign rdata1 = mem[raddr1];
   assign rdata2 = mem[raddr2];
   
   always @ (posedge clk) begin
      if (we1)
	mem[waddr1] <= wdata1;
      if (we2)
	mem[waddr2] <= wdata2;
   end
endmodule // ram_sync_nolatch_2r2w

/*
 module ram_sync_nolatch_4r1w(
 input wire 			       clk,
 input wire [BRAM_ADDR_WIDTH-1:0]       raddr1,
 input wire [BRAM_ADDR_WIDTH-1:0]       raddr2,
 input wire [BRAM_ADDR_WIDTH-1:0]       raddr3,
 input wire [BRAM_ADDR_WIDTH-1:0]       raddr4,
 output wire [BRAM_DATA_WIDTH-1:0] rdata1,
 output wire [BRAM_DATA_WIDTH-1:0] rdata2,
 output wire [BRAM_DATA_WIDTH-1:0] rdata3,
 output wire [BRAM_DATA_WIDTH-1:0] rdata4,
 input wire [BRAM_ADDR_WIDTH-1:0]       waddr,
 input wire [BRAM_DATA_WIDTH-1:0]       wdata,
 input wire 			       we
 );
 parameter BRAM_ADDR_WIDTH = `ADDR_LEN;
 parameter BRAM_DATA_WIDTH = `DATA_LEN;
 parameter DATA_DEPTH      = 32;

 ram_sync_nolatch_2r1w 
 #(BRAM_ADDR_WIDTH, BRAM_DATA_WIDTH, DATA_DEPTH) 
 mem0(
 .clk(clk),
 .raddr1(raddr1),
 .raddr2(raddr2),
 .rdata1(rdata1),
 .rdata2(rdata2),
 .waddr(waddr),
 .wdata(wdata),
 .we(we)
 );

 ram_sync_nolatch_2r1w 
 #(BRAM_ADDR_WIDTH, BRAM_DATA_WIDTH, DATA_DEPTH) 
 mem1(
 .clk(clk),
 .raddr1(raddr3),
 .raddr2(raddr4),
 .rdata1(rdata3),
 .rdata2(rdata4),
 .waddr(waddr),
 .wdata(wdata),
 .we(we)
 );
 
 endmodule //ram_sync_nolatch_4r1w
 */
module ram_sync_nolatch_4r2w #(
			       parameter BRAM_ADDR_WIDTH = `ADDR_LEN,
			       parameter BRAM_DATA_WIDTH = `DATA_LEN,
			       parameter DATA_DEPTH      = 32
			       ) 
   (
    input wire 			      clk,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr1,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr2,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr3,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr4,
    output wire [BRAM_DATA_WIDTH-1:0] rdata1,
    output wire [BRAM_DATA_WIDTH-1:0] rdata2,
    output wire [BRAM_DATA_WIDTH-1:0] rdata3,
    output wire [BRAM_DATA_WIDTH-1:0] rdata4,
    input wire [BRAM_ADDR_WIDTH-1:0]  waddr1,
    input wire [BRAM_ADDR_WIDTH-1:0]  waddr2,
    input wire [BRAM_DATA_WIDTH-1:0]  wdata1,
    input wire [BRAM_DATA_WIDTH-1:0]  wdata2,
    input wire 			      we1,
    input wire 			      we2
    );

   reg [BRAM_DATA_WIDTH-1:0] 				       mem [0:DATA_DEPTH-1];
   
   assign rdata1 = mem[raddr1];
   assign rdata2 = mem[raddr2];
   assign rdata3 = mem[raddr3];
   assign rdata4 = mem[raddr4];
   
   always @ (posedge clk) begin
      if (we1)
	mem[waddr1] <= wdata1;
      if (we2)
	mem[waddr2] <= wdata2;
   end
endmodule // ram_sync_nolatch_4r2w

/*
 module ram_sync_nolatch_6r2w(
 input wire 			       clk,
 input wire [BRAM_ADDR_WIDTH-1:0]       raddr1,
 input wire [BRAM_ADDR_WIDTH-1:0]       raddr2,
 input wire [BRAM_ADDR_WIDTH-1:0]       raddr3,
 input wire [BRAM_ADDR_WIDTH-1:0]       raddr4,
 input wire [BRAM_ADDR_WIDTH-1:0]       raddr5,
 input wire [BRAM_ADDR_WIDTH-1:0]       raddr6,
 output wire [BRAM_DATA_WIDTH-1:0] rdata1,
 output wire [BRAM_DATA_WIDTH-1:0] rdata2,
 output wire [BRAM_DATA_WIDTH-1:0] rdata3,
 output wire [BRAM_DATA_WIDTH-1:0] rdata4,
 output wire [BRAM_DATA_WIDTH-1:0] rdata5,
 output wire [BRAM_DATA_WIDTH-1:0] rdata6,
 input wire [BRAM_ADDR_WIDTH-1:0]       waddr1,
 input wire [BRAM_ADDR_WIDTH-1:0]       waddr2,
 input wire [BRAM_DATA_WIDTH-1:0]       wdata1,
 input wire [BRAM_DATA_WIDTH-1:0]       wdata2,
 input wire 			       we1,
 input wire 			       we2
 );
 parameter BRAM_ADDR_WIDTH = `ADDR_LEN;
 parameter BRAM_DATA_WIDTH = `DATA_LEN;
 parameter DATA_DEPTH      = 32;

 ram_sync_nolatch_2r2w 
 #(BRAM_ADDR_WIDTH, BRAM_DATA_WIDTH, DATA_DEPTH) 
 mem0(
 .clk(clk),
 .raddr1(raddr1),
 .raddr2(raddr2),
 .rdata1(rdata1),
 .rdata2(rdata2),
 .waddr1(waddr1),
 .waddr2(waddr2),
 .wdata1(wdata1),
 .wdata2(wdata2),
 .we1(we1),
 .we2(we2)
 );

 ram_sync_nolatch_2r2w 
 #(BRAM_ADDR_WIDTH, BRAM_DATA_WIDTH, DATA_DEPTH) 
 mem1(
 .clk(clk),
 .raddr1(raddr3),
 .raddr2(raddr4),
 .rdata1(rdata3),
 .rdata2(rdata4),
 .waddr1(waddr1),
 .waddr2(waddr2),
 .wdata1(wdata1),
 .wdata2(wdata2),
 .we1(we1),
 .we2(we2)
 );

 ram_sync_nolatch_2r2w 
 #(BRAM_ADDR_WIDTH, BRAM_DATA_WIDTH, DATA_DEPTH) 
 mem2(
 .clk(clk),
 .raddr1(raddr5),
 .raddr2(raddr6),
 .rdata1(rdata5),
 .rdata2(rdata6),
 .waddr1(waddr1),
 .waddr2(waddr2),
 .wdata1(wdata1),
 .wdata2(wdata2),
 .we1(we1),
 .we2(we2)
 );
 
 endmodule // ram_sync_nolatch_6r2w
 */
`default_nettype wire
`include "constants.vh"
`default_nettype none
module ram_sync_1r1w #(
		       parameter BRAM_ADDR_WIDTH = `ADDR_LEN,
		       parameter BRAM_DATA_WIDTH = `DATA_LEN,
		       parameter DATA_DEPTH      = 32
		       ) 
   (
    input wire 			     clk,
    input wire [BRAM_ADDR_WIDTH-1:0] raddr1,
    output reg [BRAM_DATA_WIDTH-1:0] rdata1,
    input wire [BRAM_ADDR_WIDTH-1:0] waddr,
    input wire [BRAM_DATA_WIDTH-1:0] wdata,
    input wire 			     we
    );

   reg [BRAM_DATA_WIDTH-1:0] 			      mem [0:DATA_DEPTH-1];

   always @ (posedge clk) begin
      rdata1 <= mem[raddr1];
      if (we)
	mem[waddr] <= wdata;
   end
endmodule // ram_sync_1r1w

module ram_sync_2r1w #(
		       parameter BRAM_ADDR_WIDTH = `ADDR_LEN,
		       parameter BRAM_DATA_WIDTH = `DATA_LEN,
		       parameter DATA_DEPTH      = 32
		       ) 
   (
    input wire 			     clk,
    input wire [BRAM_ADDR_WIDTH-1:0] raddr1,
    input wire [BRAM_ADDR_WIDTH-1:0] raddr2,
    output reg [BRAM_DATA_WIDTH-1:0] rdata1,
    output reg [BRAM_DATA_WIDTH-1:0] rdata2,
    input wire [BRAM_ADDR_WIDTH-1:0] waddr,
    input wire [BRAM_DATA_WIDTH-1:0] wdata,
    input wire 			     we
    );
   
   reg [BRAM_DATA_WIDTH-1:0] 			      mem [0:DATA_DEPTH-1];

   always @ (posedge clk) begin
      rdata1 <= mem[raddr1];
      rdata2 <= mem[raddr2];
      if (we)
	mem[waddr] <= wdata;
   end
endmodule // ram_sync_2r1w

module ram_sync_2r2w #(
		       parameter BRAM_ADDR_WIDTH = `ADDR_LEN,
		       parameter BRAM_DATA_WIDTH = `DATA_LEN,
		       parameter DATA_DEPTH      = 32
		       ) 
   (
    input wire 			     clk,
    input wire [BRAM_ADDR_WIDTH-1:0] raddr1,
    input wire [BRAM_ADDR_WIDTH-1:0] raddr2,
    output reg [BRAM_DATA_WIDTH-1:0] rdata1,
    output reg [BRAM_DATA_WIDTH-1:0] rdata2,
    input wire [BRAM_ADDR_WIDTH-1:0] waddr1,
    input wire [BRAM_ADDR_WIDTH-1:0] waddr2,
    input wire [BRAM_DATA_WIDTH-1:0] wdata1,
    input wire [BRAM_DATA_WIDTH-1:0] wdata2,
    input wire 			     we1,
    input wire 			     we2
    );
   
   reg [BRAM_DATA_WIDTH-1:0] 			      mem [0:DATA_DEPTH-1];

   always @ (posedge clk) begin
      rdata1 <= mem[raddr1];
      rdata2 <= mem[raddr2];
      if (we1)
	mem[waddr1] <= wdata1;
      if (we2)
	mem[waddr2] <= wdata2;
   end
endmodule // ram_sync_2r2w

module ram_sync_4r1w #(
		       parameter BRAM_ADDR_WIDTH = `ADDR_LEN,
		       parameter BRAM_DATA_WIDTH = `DATA_LEN,
		       parameter DATA_DEPTH      = 32
		       ) 
   (
    input wire 			      clk,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr1,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr2,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr3,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr4,
    output wire [BRAM_DATA_WIDTH-1:0] rdata1,
    output wire [BRAM_DATA_WIDTH-1:0] rdata2,
    output wire [BRAM_DATA_WIDTH-1:0] rdata3,
    output wire [BRAM_DATA_WIDTH-1:0] rdata4,
    input wire [BRAM_ADDR_WIDTH-1:0]  waddr,
    input wire [BRAM_DATA_WIDTH-1:0]  wdata,
    input wire 			      we
    );
   
   ram_sync_2r1w 
     #(BRAM_ADDR_WIDTH, BRAM_DATA_WIDTH, DATA_DEPTH) 
   mem0(
	.clk(clk),
	.raddr1(raddr1),
	.raddr2(raddr2),
	.rdata1(rdata1),
	.rdata2(rdata2),
	.waddr(waddr),
	.wdata(wdata),
	.we(we)
	);

   ram_sync_2r1w 
     #(BRAM_ADDR_WIDTH, BRAM_DATA_WIDTH, DATA_DEPTH) 
   mem1(
	.clk(clk),
	.raddr1(raddr3),
	.raddr2(raddr4),
	.rdata1(rdata3),
	.rdata2(rdata4),
	.waddr(waddr),
	.wdata(wdata),
	.we(we)
	);
   
endmodule // ram_sync_4r1w

module ram_sync_4r2w #(
		       parameter BRAM_ADDR_WIDTH = `ADDR_LEN,
		       parameter BRAM_DATA_WIDTH = `DATA_LEN,
		       parameter DATA_DEPTH      = 32
		       ) 
   (
    input wire 			      clk,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr1,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr2,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr3,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr4,
    output wire [BRAM_DATA_WIDTH-1:0] rdata1,
    output wire [BRAM_DATA_WIDTH-1:0] rdata2,
    output wire [BRAM_DATA_WIDTH-1:0] rdata3,
    output wire [BRAM_DATA_WIDTH-1:0] rdata4,
    input wire [BRAM_ADDR_WIDTH-1:0]  waddr1,
    input wire [BRAM_ADDR_WIDTH-1:0]  waddr2,
    input wire [BRAM_DATA_WIDTH-1:0]  wdata1,
    input wire [BRAM_DATA_WIDTH-1:0]  wdata2,
    input wire 			      we1,
    input wire 			      we2
    );

   ram_sync_2r2w 
     #(BRAM_ADDR_WIDTH, BRAM_DATA_WIDTH, DATA_DEPTH) 
   mem0(
	.clk(clk),
	.raddr1(raddr1),
	.raddr2(raddr2),
	.rdata1(rdata1),
	.rdata2(rdata2),
	.waddr1(waddr1),
	.waddr2(waddr2),
	.wdata1(wdata1),
	.wdata2(wdata2),
	.we1(we1),
	.we2(we2)
	);

   ram_sync_2r2w 
     #(BRAM_ADDR_WIDTH, BRAM_DATA_WIDTH, DATA_DEPTH) 
   mem1(
	.clk(clk),
	.raddr1(raddr3),
	.raddr2(raddr4),
	.rdata1(rdata3),
	.rdata2(rdata4),
	.waddr1(waddr1),
	.waddr2(waddr2),
	.wdata1(wdata1),
	.wdata2(wdata2),
	.we1(we1),
	.we2(we2)
	);
   
endmodule // ram_sync_4r2w

module ram_sync_6r2w #(
		       parameter BRAM_ADDR_WIDTH = `ADDR_LEN,
		       parameter BRAM_DATA_WIDTH = `DATA_LEN,
		       parameter DATA_DEPTH      = 32
		       ) 
   (
    input wire 			      clk,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr1,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr2,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr3,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr4,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr5,
    input wire [BRAM_ADDR_WIDTH-1:0]  raddr6,
    output wire [BRAM_DATA_WIDTH-1:0] rdata1,
    output wire [BRAM_DATA_WIDTH-1:0] rdata2,
    output wire [BRAM_DATA_WIDTH-1:0] rdata3,
    output wire [BRAM_DATA_WIDTH-1:0] rdata4,
    output wire [BRAM_DATA_WIDTH-1:0] rdata5,
    output wire [BRAM_DATA_WIDTH-1:0] rdata6,
    input wire [BRAM_ADDR_WIDTH-1:0]  waddr1,
    input wire [BRAM_ADDR_WIDTH-1:0]  waddr2,
    input wire [BRAM_DATA_WIDTH-1:0]  wdata1,
    input wire [BRAM_DATA_WIDTH-1:0]  wdata2,
    input wire 			      we1,
    input wire 			      we2
    );

   ram_sync_2r2w 
     #(BRAM_ADDR_WIDTH, BRAM_DATA_WIDTH, DATA_DEPTH) 
   mem0(
	.clk(clk),
	.raddr1(raddr1),
	.raddr2(raddr2),
	.rdata1(rdata1),
	.rdata2(rdata2),
	.waddr1(waddr1),
	.waddr2(waddr2),
	.wdata1(wdata1),
	.wdata2(wdata2),
	.we1(we1),
	.we2(we2)
	);

   ram_sync_2r2w 
     #(BRAM_ADDR_WIDTH, BRAM_DATA_WIDTH, DATA_DEPTH) 
   mem1(
	.clk(clk),
	.raddr1(raddr3),
	.raddr2(raddr4),
	.rdata1(rdata3),
	.rdata2(rdata4),
	.waddr1(waddr1),
	.waddr2(waddr2),
	.wdata1(wdata1),
	.wdata2(wdata2),
	.we1(we1),
	.we2(we2)
	);

   ram_sync_2r2w 
     #(BRAM_ADDR_WIDTH, BRAM_DATA_WIDTH, DATA_DEPTH) 
   mem2(
	.clk(clk),
	.raddr1(raddr5),
	.raddr2(raddr6),
	.rdata1(rdata5),
	.rdata2(rdata6),
	.waddr1(waddr1),
	.waddr2(waddr2),
	.wdata1(wdata1),
	.wdata2(wdata2),
	.we1(we1),
	.we2(we2)
	);
   
endmodule // ram_sync_6r2w
`default_nettype wire
`include "constants.vh"
`default_nettype none
module reorderbuf
  (
   input wire 			  clk,
   input wire 			  reset,
   //Write Signal
   input wire 			  dp1,
   input wire [`RRF_SEL-1:0] 	  dp1_addr,
   input wire [`INSN_LEN-1:0] 	  pc_dp1,
   input wire 			  storebit_dp1,
   input wire 			  dstvalid_dp1,
   input wire [`REG_SEL-1:0] 	  dst_dp1,
   input wire [`GSH_BHR_LEN-1:0]  bhr_dp1,
   input wire 			  isbranch_dp1,
   input wire 			  dp2,
   input wire [`RRF_SEL-1:0] 	  dp2_addr,
   input wire [`INSN_LEN-1:0] 	  pc_dp2,
   input wire 			  storebit_dp2,
   input wire 			  dstvalid_dp2,
   input wire [`REG_SEL-1:0] 	  dst_dp2,
   input wire [`GSH_BHR_LEN-1:0]  bhr_dp2,
   input wire 			  isbranch_dp2,
   input wire 			  exfin_alu1,
   input wire [`RRF_SEL-1:0] 	  exfin_alu1_addr,
   input wire 			  exfin_alu2,
   input wire [`RRF_SEL-1:0] 	  exfin_alu2_addr,
   input wire 			  exfin_mul,
   input wire [`RRF_SEL-1:0] 	  exfin_mul_addr,
   input wire 			  exfin_ldst,
   input wire [`RRF_SEL-1:0] 	  exfin_ldst_addr,
   input wire 			  exfin_branch,
   input wire [`RRF_SEL-1:0] 	  exfin_branch_addr,
   input wire 			  exfin_branch_brcond,
   input wire [`ADDR_LEN-1:0] 	  exfin_branch_jmpaddr, 
  
   output reg [`RRF_SEL-1:0] 	  comptr,
   output wire [`RRF_SEL-1:0] 	  comptr2,
   output wire [1:0] 		  comnum,
   output wire 			  stcommit,
   output wire 			  arfwe1,
   output wire 			  arfwe2,
   output wire [`REG_SEL-1:0] 	  dstarf1,
   output wire [`REG_SEL-1:0] 	  dstarf2,
   output wire [`ADDR_LEN-1:0] 	  pc_combranch,
   output wire [`GSH_BHR_LEN-1:0] bhr_combranch,
   output wire 			  brcond_combranch,
   output wire [`ADDR_LEN-1:0] 	  jmpaddr_combranch,
   output wire 			  combranch,
   input wire [`RRF_SEL-1:0] 	  dispatchptr,
   input wire [`RRF_SEL:0] 	  rrf_freenum,
   input wire 			  prmiss
   );

   reg [`RRF_NUM-1:0] 		  finish;
   reg [`RRF_NUM-1:0] 		  storebit;
   reg [`RRF_NUM-1:0] 		  dstvalid;
   reg [`RRF_NUM-1:0] 		  brcond;
   reg [`RRF_NUM-1:0] 		  isbranch;
   
   reg [`ADDR_LEN-1:0] 		  inst_pc [0:`RRF_NUM-1];
   reg [`ADDR_LEN-1:0] 		  jmpaddr [0:`RRF_NUM-1];   
   reg [`REG_SEL-1:0] 		  dst [0:`RRF_NUM-1];
   reg [`GSH_BHR_LEN-1:0] 	  bhr [0:`RRF_NUM-1];
   
   assign comptr2 = comptr+1;
   
   wire 			  hidp = (comptr > dispatchptr) || (rrf_freenum == 0) ?
				  1'b1 : 1'b0;
   wire 			  com_en1 = ({hidp, dispatchptr} - {1'b0, comptr}) > 0 ? 1'b1 : 1'b0;
   wire 			  com_en2 = ({hidp, dispatchptr} - {1'b0, comptr}) > 1 ? 1'b1 : 1'b0;
   wire 			  commit1 = com_en1 & finish[comptr];
   //   wire commit2 = commit1 & com_en2 & finish[comptr2];

   wire 			  commit2 = 
				  ~(~prmiss & commit1 & isbranch[comptr]) &
				  ~(commit1 & storebit[comptr] & ~prmiss) &
				  commit1 & com_en2 & finish[comptr2];

   assign comnum = {1'b0, commit1} + {1'b0, commit2};
   assign stcommit = (commit1 & storebit[comptr] & ~prmiss) |
		     (commit2 & storebit[comptr2] & ~prmiss);
   assign arfwe1 = ~prmiss & commit1 & dstvalid[comptr];
   assign arfwe2 = ~prmiss & commit2 & dstvalid[comptr2];
   assign dstarf1 = dst[comptr];
   assign dstarf2 = dst[comptr2];
   assign combranch = (~prmiss & commit1 & isbranch[comptr]) |
		      (~prmiss & commit2 & isbranch[comptr2]);
   assign pc_combranch = (~prmiss & commit1 & isbranch[comptr]) ? 
			 inst_pc[comptr] : inst_pc[comptr2];
   assign bhr_combranch = (~prmiss & commit1 & isbranch[comptr]) ?
			  bhr[comptr] : bhr[comptr2];
   assign brcond_combranch = (~prmiss & commit1 & isbranch[comptr]) ?
			     brcond[comptr] : brcond[comptr2];
   assign jmpaddr_combranch = (~prmiss & commit1 & isbranch[comptr]) ?
			      jmpaddr[comptr] : jmpaddr[comptr2];
   

   always @ (posedge clk) begin
      if (reset) begin
	 comptr <= 0;
      end else if (~prmiss) begin
	 comptr <= comptr + commit1 + commit2;
      end
   end
   
   always @ (posedge clk) begin
      if (reset) begin
	 finish <= 0;
	 brcond <= 0;
      end else begin
	 if (dp1)
	   finish[dp1_addr] <= 1'b0;
	 if (dp2)
	   finish[dp2_addr] <= 1'b0;
	 if (exfin_alu1)
	   finish[exfin_alu1_addr] <= 1'b1;
	 if (exfin_alu2)
	   finish[exfin_alu2_addr] <= 1'b1;
	 if (exfin_mul)
	   finish[exfin_mul_addr] <= 1'b1;
	 if (exfin_ldst)
	   finish[exfin_ldst_addr] <= 1'b1;
	 if (exfin_branch) begin
	    finish[exfin_branch_addr] <= 1'b1;
	    brcond[exfin_branch_addr] <= exfin_branch_brcond;
	    jmpaddr[exfin_branch_addr] <= exfin_branch_jmpaddr;
	 end
      end
   end // always @ (posedge clk)

   always @ (posedge clk) begin
      if (dp1) begin
	 isbranch[dp1_addr] <= isbranch_dp1;
	 storebit[dp1_addr] <= storebit_dp1;
	 dstvalid[dp1_addr] <= dstvalid_dp1;
	 dst[dp1_addr] <= dst_dp1;
	 bhr[dp1_addr] <= bhr_dp1;
	 inst_pc[dp1_addr] <= pc_dp1;
      end
      if (dp2) begin
	 isbranch[dp2_addr] <= isbranch_dp2;
	 storebit[dp2_addr] <= storebit_dp2;
	 dstvalid[dp2_addr] <= dstvalid_dp2;
	 dst[dp2_addr] <= dst_dp2;
	 bhr[dp2_addr] <= bhr_dp2;
	 inst_pc[dp2_addr] <= pc_dp2;
      end
   end
endmodule // reorderbuf
`default_nettype wire
`include "constants.vh"
`default_nettype none
module rrf_freelistmanager
  (
   input wire 		      clk,
   input wire 		      reset,
   input wire 		      invalid1,
   input wire 		      invalid2,
   input wire [1:0] 	      comnum,
   input wire 		      prmiss,
   input wire [`RRF_SEL-1:0]  rrftagfix,
   output wire [`RRF_SEL-1:0] rename_dst1,
   output wire [`RRF_SEL-1:0] rename_dst2,
   output wire 		      allocatable,
   input wire 		      stall_DP, //= ~allocatable && ~prmiss
   output reg [`RRF_SEL:0]    freenum,
   output reg [`RRF_SEL-1:0]  rrfptr,
   input wire [`RRF_SEL-1:0]  comptr,
   output reg 		      nextrrfcyc
   );
   
   wire [1:0] 		      reqnum = {1'b0, ~invalid1} + {1'b0, ~invalid2};
   wire 		      hi = (comptr > rrftagfix) ? 1'b1 : 1'b0;
   wire [`RRF_SEL-1:0] 	      rrfptr_next = rrfptr + reqnum;
   
   assign allocatable = (freenum + comnum) < reqnum ? 1'b0 : 1'b1;
   assign rename_dst1 = rrfptr;
   assign rename_dst2 = rrfptr + (~invalid1 ? 1 : 0);
   
   always @ (posedge clk) begin
      if (reset) begin
	 freenum <= `RRF_NUM;
	 rrfptr <= 0;
	 nextrrfcyc <= 0;
      end else if (prmiss) begin
	 rrfptr <= rrftagfix; //== prmiss_rrftag+1
	 freenum <= `RRF_NUM - ({hi, rrftagfix} - {1'b0, comptr});
	 nextrrfcyc <= 0;
      end else if (stall_DP) begin
	 rrfptr <= rrfptr;
	 freenum <= freenum + comnum;
	 nextrrfcyc <= 0;
      end else begin
	 rrfptr <= rrfptr_next;
	 freenum <= freenum + comnum - reqnum;
	 nextrrfcyc <= (rrfptr > rrfptr_next) ? 1'b1 : 1'b0;
      end
   end
endmodule // rrf_freelistmanager


`default_nettype wire
`include "constants.vh"

/*
 clear valid when dpen
 set valid when wrrfen
 */
`default_nettype none
module rrf(
	   input wire 		       clk,
	   input wire 		       reset,
	   input wire [`RRF_SEL-1:0]   rs1_1tag,
	   input wire [`RRF_SEL-1:0]   rs2_1tag,
	   input wire [`RRF_SEL-1:0]   rs1_2tag,
	   input wire [`RRF_SEL-1:0]   rs2_2tag,
	   input wire [`RRF_SEL-1:0]   com1tag,
	   input wire [`RRF_SEL-1:0]   com2tag,
	   output wire 		       rs1_1valid,
	   output wire 		       rs2_1valid,
	   output wire 		       rs1_2valid,
	   output wire 		       rs2_2valid,
	   output wire [`DATA_LEN-1:0] rs1_1data,
	   output wire [`DATA_LEN-1:0] rs2_1data,
	   output wire [`DATA_LEN-1:0] rs1_2data,
	   output wire [`DATA_LEN-1:0] rs2_2data,
	   output wire [`DATA_LEN-1:0] com1data,
	   output wire [`DATA_LEN-1:0] com2data,
	   input wire [`RRF_SEL-1:0]   wrrfaddr1,
	   input wire [`RRF_SEL-1:0]   wrrfaddr2,
	   input wire [`RRF_SEL-1:0]   wrrfaddr3,
	   input wire [`RRF_SEL-1:0]   wrrfaddr4,
	   input wire [`RRF_SEL-1:0]   wrrfaddr5,
	   input wire [`DATA_LEN-1:0]  wrrfdata1,
	   input wire [`DATA_LEN-1:0]  wrrfdata2,
	   input wire [`DATA_LEN-1:0]  wrrfdata3,
	   input wire [`DATA_LEN-1:0]  wrrfdata4,
	   input wire [`DATA_LEN-1:0]  wrrfdata5,
	   input wire 		       wrrfen1,
	   input wire 		       wrrfen2,
	   input wire 		       wrrfen3,
	   input wire 		       wrrfen4,
	   input wire 		       wrrfen5,
	   input wire [`RRF_SEL-1:0]   dpaddr1,
	   input wire [`RRF_SEL-1:0]   dpaddr2,
	   input wire 		       dpen1,
	   input wire 		       dpen2
	   );

   reg [`RRF_NUM-1:0] 		       valid;
   reg [`DATA_LEN-1:0] 		       datarr [0:`RRF_NUM-1];

   assign rs1_1data = datarr[rs1_1tag];
   assign rs2_1data = datarr[rs2_1tag];
   assign rs1_2data = datarr[rs1_2tag];
   assign rs2_2data = datarr[rs2_2tag];
   assign com1data = datarr[com1tag];
   assign com2data = datarr[com2tag];

   assign rs1_1valid = valid[rs1_1tag];
   assign rs2_1valid = valid[rs2_1tag];
   assign rs1_2valid = valid[rs1_2tag];
   assign rs2_2valid = valid[rs2_2tag];

   wire [`RRF_NUM-1:0] 		       or_valid = 
				       (~wrrfen1 ? `RRF_NUM'b0 : 
					(`RRF_NUM'b1 << wrrfaddr1)) |
				       (~wrrfen2 ? `RRF_NUM'b0 : 
					(`RRF_NUM'b1 << wrrfaddr2)) |
 				       (~wrrfen3 ? `RRF_NUM'b0 : 
					(`RRF_NUM'b1 << wrrfaddr3)) |
				       (~wrrfen4 ? `RRF_NUM'b0 : 
					(`RRF_NUM'b1 << wrrfaddr4)) |
				       (~wrrfen5 ? `RRF_NUM'b0 : 
					(`RRF_NUM'b1 << wrrfaddr5));
   
   wire [`RRF_NUM-1:0] 		       and_valid = 
				       (~dpen1 ? ~(`RRF_NUM'b0) : 
					~(`RRF_NUM'b1 << dpaddr1)) & 
				       (~dpen2 ? ~(`RRF_NUM'b0) : 
					~(`RRF_NUM'b1 << dpaddr2));

   always @ (posedge clk) begin
      if (reset) begin
	 valid <= 0;
      end else begin
	 valid <= (valid | or_valid) & and_valid;
      end
   end

   always @ (posedge clk) begin
      if (~reset) begin
	 if (wrrfen1)
	   datarr[wrrfaddr1] <= wrrfdata1;
	 if (wrrfen2)
	   datarr[wrrfaddr2] <= wrrfdata2;
	 if (wrrfen3)
	   datarr[wrrfaddr3] <= wrrfdata3;
	 if (wrrfen4)
	   datarr[wrrfaddr4] <= wrrfdata4;
	 if (wrrfen5)
	   datarr[wrrfaddr5] <= wrrfdata5;
      end
   end
endmodule // rrf
`default_nettype wire
`include "constants.vh"
`include "alu_ops.vh"
`include "rv32_opcodes.vh"
`default_nettype none
module rs_alu_ent
  (
   //Memory
   input wire 			     clk,
   input wire 			     reset,
   input wire 			     busy,
   input wire [`ADDR_LEN-1:0] 	     wpc,
   input wire [`DATA_LEN-1:0] 	     wsrc1,
   input wire [`DATA_LEN-1:0] 	     wsrc2,
   input wire 			     wvalid1,
   input wire 			     wvalid2,
   input wire [`DATA_LEN-1:0] 	     wimm,
   input wire [`RRF_SEL-1:0] 	     wrrftag,
   input wire 			     wdstval,
   input wire [`SRC_A_SEL_WIDTH-1:0] wsrc_a,
   input wire [`SRC_B_SEL_WIDTH-1:0] wsrc_b,
   input wire [`ALU_OP_WIDTH-1:0]    walu_op,
   input wire [`SPECTAG_LEN-1:0]     wspectag,
   input wire 			     we,
   output wire [`DATA_LEN-1:0] 	     ex_src1,
   output wire [`DATA_LEN-1:0] 	     ex_src2,
   output wire 			     ready,
   output reg [`ADDR_LEN-1:0] 	     pc,
   output reg [`DATA_LEN-1:0] 	     imm,
   output reg [`RRF_SEL-1:0] 	     rrftag,
   output reg 			     dstval,
   output reg [`SRC_A_SEL_WIDTH-1:0] src_a,
   output reg [`SRC_B_SEL_WIDTH-1:0] src_b,
   output reg [`ALU_OP_WIDTH-1:0]    alu_op,
   output reg [`SPECTAG_LEN-1:0]     spectag,
   //EXRSLT
   input wire [`DATA_LEN-1:0] 	     exrslt1,
   input wire [`RRF_SEL-1:0] 	     exdst1,
   input wire 			     kill_spec1,
   input wire [`DATA_LEN-1:0] 	     exrslt2,
   input wire [`RRF_SEL-1:0] 	     exdst2,
   input wire 			     kill_spec2,
   input wire [`DATA_LEN-1:0] 	     exrslt3,
   input wire [`RRF_SEL-1:0] 	     exdst3,
   input wire 			     kill_spec3,
   input wire [`DATA_LEN-1:0] 	     exrslt4,
   input wire [`RRF_SEL-1:0] 	     exdst4,
   input wire 			     kill_spec4,
   input wire [`DATA_LEN-1:0] 	     exrslt5,
   input wire [`RRF_SEL-1:0] 	     exdst5,
   input wire 			     kill_spec5
   );

   reg [`DATA_LEN-1:0] 		     src1;
   reg [`DATA_LEN-1:0] 		     src2;
   reg 				     valid1;
   reg 				     valid2;

   wire [`DATA_LEN-1:0] 	     nextsrc1;
   wire [`DATA_LEN-1:0] 	     nextsrc2;   
   wire 			     nextvalid1;
   wire 			     nextvalid2;
   
   assign ready = busy & valid1 & valid2;
   assign ex_src1 = ~valid1 & nextvalid1 ?
		    nextsrc1 : src1;
   assign ex_src2 = ~valid2 & nextvalid2 ?
		    nextsrc2 : src2;
   
   always @ (posedge clk) begin
      if (reset) begin
	 pc <= 0;
	 imm <= 0;
	 rrftag <= 0;
	 dstval <= 0;
	 src_a <= 0;
	 src_b <= 0;
	 alu_op <= 0;
	 spectag <= 0;

	 src1 <= 0;
	 src2 <= 0;
	 valid1 <= 0;
	 valid2 <= 0;
      end else if (we) begin
	 pc <= wpc;
	 imm <= wimm;
	 rrftag <= wrrftag;
	 dstval <= wdstval;
	 src_a <= wsrc_a;
	 src_b <= wsrc_b;
	 alu_op <= walu_op;
	 spectag <= wspectag;

	 src1 <= wsrc1;
	 src2 <= wsrc2;
	 valid1 <= wvalid1;
	 valid2 <= wvalid2;
      end else begin // if (we)
	 src1 <= nextsrc1;
	 src2 <= nextsrc2;
	 valid1 <= nextvalid1;
	 valid2 <= nextvalid2;
      end
   end
   
   src_manager srcmng1(
		       .opr(src1),
		       .opr_rdy(valid1),
		       .exrslt1(exrslt1),
		       .exdst1(exdst1),
		       .kill_spec1(kill_spec1),
		       .exrslt2(exrslt2),
		       .exdst2(exdst2),
		       .kill_spec2(kill_spec2),
		       .exrslt3(exrslt3),
		       .exdst3(exdst3),
		       .kill_spec3(kill_spec3),
		       .exrslt4(exrslt4),
		       .exdst4(exdst4),
		       .kill_spec4(kill_spec4),
		       .exrslt5(exrslt5),
		       .exdst5(exdst5),
		       .kill_spec5(kill_spec5),
		       .src(nextsrc1),
		       .resolved(nextvalid1)
		       );

   src_manager srcmng2(
		       .opr(src2),
		       .opr_rdy(valid2),
		       .exrslt1(exrslt1),
		       .exdst1(exdst1),
		       .kill_spec1(kill_spec1),
		       .exrslt2(exrslt2),
		       .exdst2(exdst2),
		       .kill_spec2(kill_spec2),
		       .exrslt3(exrslt3),
		       .exdst3(exdst3),
		       .kill_spec3(kill_spec3),
		       .exrslt4(exrslt4),
		       .exdst4(exdst4),
		       .kill_spec4(kill_spec4),
		       .exrslt5(exrslt5),
		       .exdst5(exdst5),
		       .kill_spec5(kill_spec5),
		       .src(nextsrc2),
		       .resolved(nextvalid2)
		       );
   
endmodule // rs_alu


module rs_alu
  (
   //System
   input wire 				       clk,
   input wire 				       reset,
   output reg [`ALU_ENT_NUM-1:0] 	       busyvec,
   input wire 				       prmiss,
   input wire 				       prsuccess,
   input wire [`SPECTAG_LEN-1:0] 	       prtag,
   input wire [`SPECTAG_LEN-1:0] 	       specfixtag,
   output wire [`ALU_ENT_NUM*(`RRF_SEL+2)-1:0] histvect,
   input wire 				       nextrrfcyc, 
   //WriteSignal
   input wire 				       clearbusy, //Issue
   input wire [`ALU_ENT_SEL-1:0] 	       issueaddr,
   input wire 				       we1, //alloc1
   input wire 				       we2, //alloc2
   input wire [`ALU_ENT_SEL-1:0] 	       waddr1, //allocent1
   input wire [`ALU_ENT_SEL-1:0] 	       waddr2, //allocent2
   //WriteSignal1
   input wire [`ADDR_LEN-1:0] 		       wpc_1,
   input wire [`DATA_LEN-1:0] 		       wsrc1_1,
   input wire [`DATA_LEN-1:0] 		       wsrc2_1,
   input wire 				       wvalid1_1,
   input wire 				       wvalid2_1,
   input wire [`DATA_LEN-1:0] 		       wimm_1,
   input wire [`RRF_SEL-1:0] 		       wrrftag_1,
   input wire 				       wdstval_1,
   input wire [`SRC_A_SEL_WIDTH-1:0] 	       wsrc_a_1,
   input wire [`SRC_B_SEL_WIDTH-1:0] 	       wsrc_b_1,
   input wire [`ALU_OP_WIDTH-1:0] 	       walu_op_1,
   input wire [`SPECTAG_LEN-1:0] 	       wspectag_1,
   input wire 				       wspecbit_1,
   //WriteSignal2
   input wire [`ADDR_LEN-1:0] 		       wpc_2,
   input wire [`DATA_LEN-1:0] 		       wsrc1_2,
   input wire [`DATA_LEN-1:0] 		       wsrc2_2,
   input wire 				       wvalid1_2,
   input wire 				       wvalid2_2,
   input wire [`DATA_LEN-1:0] 		       wimm_2,
   input wire [`RRF_SEL-1:0] 		       wrrftag_2,
   input wire 				       wdstval_2,
   input wire [`SRC_A_SEL_WIDTH-1:0] 	       wsrc_a_2,
   input wire [`SRC_B_SEL_WIDTH-1:0] 	       wsrc_b_2,
   input wire [`ALU_OP_WIDTH-1:0] 	       walu_op_2,
   input wire [`SPECTAG_LEN-1:0] 	       wspectag_2,
   input wire 				       wspecbit_2,

   //ReadSignal
   output wire [`DATA_LEN-1:0] 		       ex_src1,
   output wire [`DATA_LEN-1:0] 		       ex_src2,
   output wire [`ALU_ENT_NUM-1:0] 	       ready,
   output wire [`ADDR_LEN-1:0] 		       pc,
   output wire [`DATA_LEN-1:0] 		       imm,
   output wire [`RRF_SEL-1:0] 		       rrftag,
   output wire 				       dstval,
   output wire [`SRC_A_SEL_WIDTH-1:0] 	       src_a,
   output wire [`SRC_B_SEL_WIDTH-1:0] 	       src_b,
   output wire [`ALU_OP_WIDTH-1:0] 	       alu_op,
   output wire [`SPECTAG_LEN-1:0] 	       spectag,
   output wire 				       specbit,
  
   //EXRSLT
   input wire [`DATA_LEN-1:0] 		       exrslt1,
   input wire [`RRF_SEL-1:0] 		       exdst1,
   input wire 				       kill_spec1,
   input wire [`DATA_LEN-1:0] 		       exrslt2,
   input wire [`RRF_SEL-1:0] 		       exdst2,
   input wire 				       kill_spec2,
   input wire [`DATA_LEN-1:0] 		       exrslt3,
   input wire [`RRF_SEL-1:0] 		       exdst3,
   input wire 				       kill_spec3,
   input wire [`DATA_LEN-1:0] 		       exrslt4,
   input wire [`RRF_SEL-1:0] 		       exdst4,
   input wire 				       kill_spec4,
   input wire [`DATA_LEN-1:0] 		       exrslt5,
   input wire [`RRF_SEL-1:0] 		       exdst5,
   input wire 				       kill_spec5
   );
   
   //_0
   wire [`DATA_LEN-1:0] 	      ex_src1_0;
   wire [`DATA_LEN-1:0] 	      ex_src2_0;
   wire 			      ready_0;
   wire [`ADDR_LEN-1:0] 	      pc_0;
   wire [`DATA_LEN-1:0] 	      imm_0;
   wire [`RRF_SEL-1:0] 		      rrftag_0;
   wire 			      dstval_0;
   wire [`SRC_A_SEL_WIDTH-1:0] 	      src_a_0;
   wire [`SRC_B_SEL_WIDTH-1:0] 	      src_b_0;
   wire [`ALU_OP_WIDTH-1:0] 	      alu_op_0;
   wire [`SPECTAG_LEN-1:0] 	      spectag_0;
   //_1
   wire [`DATA_LEN-1:0] 	      ex_src1_1;
   wire [`DATA_LEN-1:0] 	      ex_src2_1;
   wire 			      ready_1;
   wire [`ADDR_LEN-1:0] 	      pc_1;
   wire [`DATA_LEN-1:0] 	      imm_1;
   wire [`RRF_SEL-1:0] 		      rrftag_1;
   wire 			      dstval_1;
   wire [`SRC_A_SEL_WIDTH-1:0] 	      src_a_1;
   wire [`SRC_B_SEL_WIDTH-1:0] 	      src_b_1;
   wire [`ALU_OP_WIDTH-1:0] 	      alu_op_1;
   wire [`SPECTAG_LEN-1:0] 	      spectag_1;
   //_2
   wire [`DATA_LEN-1:0] 	      ex_src1_2;
   wire [`DATA_LEN-1:0] 	      ex_src2_2;
   wire 			      ready_2;
   wire [`ADDR_LEN-1:0] 	      pc_2;
   wire [`DATA_LEN-1:0] 	      imm_2;
   wire [`RRF_SEL-1:0] 		      rrftag_2;
   wire 			      dstval_2;
   wire [`SRC_A_SEL_WIDTH-1:0] 	      src_a_2;
   wire [`SRC_B_SEL_WIDTH-1:0] 	      src_b_2;
   wire [`ALU_OP_WIDTH-1:0] 	      alu_op_2;
   wire [`SPECTAG_LEN-1:0] 	      spectag_2;
   //_3
   wire [`DATA_LEN-1:0] 	      ex_src1_3;
   wire [`DATA_LEN-1:0] 	      ex_src2_3;
   wire 			      ready_3;
   wire [`ADDR_LEN-1:0] 	      pc_3;
   wire [`DATA_LEN-1:0] 	      imm_3;
   wire [`RRF_SEL-1:0] 		      rrftag_3;
   wire 			      dstval_3;
   wire [`SRC_A_SEL_WIDTH-1:0] 	      src_a_3;
   wire [`SRC_B_SEL_WIDTH-1:0] 	      src_b_3;
   wire [`ALU_OP_WIDTH-1:0] 	      alu_op_3;
   wire [`SPECTAG_LEN-1:0] 	      spectag_3;
   //_4
   wire [`DATA_LEN-1:0] 	      ex_src1_4;
   wire [`DATA_LEN-1:0] 	      ex_src2_4;
   wire 			      ready_4;
   wire [`ADDR_LEN-1:0] 	      pc_4;
   wire [`DATA_LEN-1:0] 	      imm_4;
   wire [`RRF_SEL-1:0] 		      rrftag_4;
   wire 			      dstval_4;
   wire [`SRC_A_SEL_WIDTH-1:0] 	      src_a_4;
   wire [`SRC_B_SEL_WIDTH-1:0] 	      src_b_4;
   wire [`ALU_OP_WIDTH-1:0] 	      alu_op_4;
   wire [`SPECTAG_LEN-1:0] 	      spectag_4;
   //_5
   wire [`DATA_LEN-1:0] 	      ex_src1_5;
   wire [`DATA_LEN-1:0] 	      ex_src2_5;
   wire 			      ready_5;
   wire [`ADDR_LEN-1:0] 	      pc_5;
   wire [`DATA_LEN-1:0] 	      imm_5;
   wire [`RRF_SEL-1:0] 		      rrftag_5;
   wire 			      dstval_5;
   wire [`SRC_A_SEL_WIDTH-1:0] 	      src_a_5;
   wire [`SRC_B_SEL_WIDTH-1:0] 	      src_b_5;
   wire [`ALU_OP_WIDTH-1:0] 	      alu_op_5;
   wire [`SPECTAG_LEN-1:0] 	      spectag_5;
   //_6
   wire [`DATA_LEN-1:0] 	      ex_src1_6;
   wire [`DATA_LEN-1:0] 	      ex_src2_6;
   wire 			      ready_6;
   wire [`ADDR_LEN-1:0] 	      pc_6;
   wire [`DATA_LEN-1:0] 	      imm_6;
   wire [`RRF_SEL-1:0] 		      rrftag_6;
   wire 			      dstval_6;
   wire [`SRC_A_SEL_WIDTH-1:0] 	      src_a_6;
   wire [`SRC_B_SEL_WIDTH-1:0] 	      src_b_6;
   wire [`ALU_OP_WIDTH-1:0] 	      alu_op_6;
   wire [`SPECTAG_LEN-1:0] 	      spectag_6;
   //_7
   wire [`DATA_LEN-1:0] 	      ex_src1_7;
   wire [`DATA_LEN-1:0] 	      ex_src2_7;
   wire 			      ready_7;
   wire [`ADDR_LEN-1:0] 	      pc_7;
   wire [`DATA_LEN-1:0] 	      imm_7;
   wire [`RRF_SEL-1:0] 		      rrftag_7;
   wire 			      dstval_7;
   wire [`SRC_A_SEL_WIDTH-1:0] 	      src_a_7;
   wire [`SRC_B_SEL_WIDTH-1:0] 	      src_b_7;
   wire [`ALU_OP_WIDTH-1:0] 	      alu_op_7;
   wire [`SPECTAG_LEN-1:0] 	      spectag_7;

   reg [`ALU_ENT_NUM-1:0] 	      specbitvec;
   reg [`ALU_ENT_NUM-1:0] 	      sortbit;
   
   
   wire [`ALU_ENT_NUM-1:0] 	      inv_vector =
				      {(spectag_7 & specfixtag) == 0 ? 1'b1 : 1'b0,
				       (spectag_6 & specfixtag) == 0 ? 1'b1 : 1'b0,
				       (spectag_5 & specfixtag) == 0 ? 1'b1 : 1'b0,
				       (spectag_4 & specfixtag) == 0 ? 1'b1 : 1'b0,
				       (spectag_3 & specfixtag) == 0 ? 1'b1 : 1'b0,
				       (spectag_2 & specfixtag) == 0 ? 1'b1 : 1'b0,
				       (spectag_1 & specfixtag) == 0 ? 1'b1 : 1'b0,
				       (spectag_0 & specfixtag) == 0 ? 1'b1 : 1'b0};

   wire [`ALU_ENT_NUM-1:0] 	      inv_vector_spec =
				      {(spectag_7 == prtag) ? 1'b0 : 1'b1,
				       (spectag_6 == prtag) ? 1'b0 : 1'b1,
				       (spectag_5 == prtag) ? 1'b0 : 1'b1,
				       (spectag_4 == prtag) ? 1'b0 : 1'b1,
				       (spectag_3 == prtag) ? 1'b0 : 1'b1,
				       (spectag_2 == prtag) ? 1'b0 : 1'b1,
				       (spectag_1 == prtag) ? 1'b0 : 1'b1,
				       (spectag_0 == prtag) ? 1'b0 : 1'b1};

   wire [`ALU_ENT_NUM-1:0] 	      specbitvec_next =
				      (inv_vector_spec & specbitvec);
   /* |
    (we1 & wspecbit_1 ? (`ALU_ENT_SEL'b1 << waddr1) : 0) |
    (we2 & wspecbit_2 ? (`ALU_ENT_SEL'b1 << waddr2) : 0);
    */
   assign specbit = prsuccess ? 
		    specbitvec_next[issueaddr] : specbitvec[issueaddr];
   
   /*   
    assign specbit = prsuccess ? 
    ((inv_vector & busyvec) |
    (we1 & wspecbit_1 ? (`ALU_ENT_SEL'b1 << waddr1) : 0) |
    (we2 & wspecbit_2 ? (`ALU_ENT_SEL'b1 << waddr2) : 0)) : 
    specbitvec[issueaddr];
    */
   
   assign ready = {ready_7, ready_6, ready_5, ready_4,
		   ready_3, ready_2, ready_1, ready_0};

   assign histvect = {
		      {~ready_7, sortbit[7], rrftag_7},
		      {~ready_6, sortbit[6], rrftag_6},
		      {~ready_5, sortbit[5], rrftag_5},
		      {~ready_4, sortbit[4], rrftag_4},
		      {~ready_3, sortbit[3], rrftag_3},
		      {~ready_2, sortbit[2], rrftag_2},
		      {~ready_1, sortbit[1], rrftag_1},
		      {~ready_0, sortbit[0], rrftag_0}		      
		      };

   always @ (posedge clk) begin
      if (reset) begin
	 sortbit <= `ALU_ENT_NUM'b1;
      end else if (nextrrfcyc) begin
	 sortbit <= (we1 ? (`ALU_ENT_NUM'b1 << waddr1) : `ALU_ENT_NUM'b0) |
		    (we2 ? (`ALU_ENT_NUM'b1 << waddr2) : `ALU_ENT_NUM'b0);
      end else begin
	 if (we1) begin
	    sortbit[waddr1] <= 1'b1;
	 end
	 if (we2) begin
	    sortbit[waddr2] <= 1'b1;
	 end
      end
   end
   
   always @ (posedge clk) begin
      if (reset) begin
	 busyvec <= 0;
	 specbitvec <= 0;
      end else begin
	 if (prmiss) begin
	    busyvec <= inv_vector & busyvec;
	    specbitvec <= 0;
	 end else if (prsuccess) begin
	    /*
	     specbitvec <= (inv_vector & busyvec) |
	     (we1 & wspecbit_1 ? (`ALU_ENT_SEL'b1 << waddr1) : 0) |
	     (we2 & wspecbit_2 ? (`ALU_ENT_SEL'b1 << waddr2) : 0);
	     */
	    specbitvec <= specbitvec_next;
	    /*
	     if (we1) begin
	     busyvec[waddr1] <= 1'b1;
	    end
	     if (we2) begin
	     busyvec[waddr2] <= 1'b1;
	    end
	     */
	    if (clearbusy) begin
	       busyvec[issueaddr] <= 1'b0;
	    end
	 end else begin
	    if (we1) begin
	       busyvec[waddr1] <= 1'b1;
	       specbitvec[waddr1] <= wspecbit_1;
	    end
	    if (we2) begin
	       busyvec[waddr2] <= 1'b1;
	       specbitvec[waddr2] <= wspecbit_2;
	    end
	    if (clearbusy) begin
	       busyvec[issueaddr] <= 1'b0;
	    end
	 end
      end
   end

   rs_alu_ent ent0(
		   .clk(clk),
		   .reset(reset),
		   .busy(busyvec[0]),
		   .wpc((we1 && (waddr1 == 0)) ? wpc_1 : wpc_2),
		   .wsrc1((we1 && (waddr1 == 0)) ? wsrc1_1 : wsrc1_2),
		   .wsrc2((we1 && (waddr1 == 0)) ? wsrc2_1 : wsrc2_2),
		   .wvalid1((we1 && (waddr1 == 0)) ? wvalid1_1 : wvalid1_2),
		   .wvalid2((we1 && (waddr1 == 0)) ? wvalid2_1 : wvalid2_2),
		   .wimm((we1 && (waddr1 == 0)) ? wimm_1 : wimm_2),
		   .wrrftag((we1 && (waddr1 == 0)) ? wrrftag_1 : wrrftag_2),
		   .wdstval((we1 && (waddr1 == 0)) ? wdstval_1 : wdstval_2),
		   .wsrc_a((we1 && (waddr1 == 0)) ? wsrc_a_1 : wsrc_a_2),
		   .wsrc_b((we1 && (waddr1 == 0)) ? wsrc_b_1 : wsrc_b_2),
		   .walu_op((we1 && (waddr1 == 0)) ? walu_op_1 : walu_op_2),
		   .wspectag((we1 && (waddr1 == 0)) ? wspectag_1 : wspectag_2),
		   .we((we1 && (waddr1 == 0)) || (we2 && (waddr2 == 0))),
		   .ex_src1(ex_src1_0),
		   .ex_src2(ex_src2_0),
		   .ready(ready_0),
		   .pc(pc_0),
		   .imm(imm_0),
		   .rrftag(rrftag_0),
		   .dstval(dstval_0),
		   .src_a(src_a_0),
		   .src_b(src_b_0),
		   .alu_op(alu_op_0),
		   .spectag(spectag_0),
		   .exrslt1(exrslt1),
		   .exdst1(exdst1),
		   .kill_spec1(kill_spec1),
		   .exrslt2(exrslt2),
		   .exdst2(exdst2),
		   .kill_spec2(kill_spec2),
		   .exrslt3(exrslt3),
		   .exdst3(exdst3),
		   .kill_spec3(kill_spec3),
		   .exrslt4(exrslt4),
		   .exdst4(exdst4),
		   .kill_spec4(kill_spec4),
		   .exrslt5(exrslt5),
		   .exdst5(exdst5),
		   .kill_spec5(kill_spec5)
		   );

   rs_alu_ent ent1(
		   .clk(clk),
		   .reset(reset),		   
		   .busy(busyvec[1]),
		   .wpc((we1 && (waddr1 == 1)) ? wpc_1 : wpc_2),
		   .wsrc1((we1 && (waddr1 == 1)) ? wsrc1_1 : wsrc1_2),
		   .wsrc2((we1 && (waddr1 == 1)) ? wsrc2_1 : wsrc2_2),
		   .wvalid1((we1 && (waddr1 == 1)) ? wvalid1_1 : wvalid1_2),
		   .wvalid2((we1 && (waddr1 == 1)) ? wvalid2_1 : wvalid2_2),
		   .wimm((we1 && (waddr1 == 1)) ? wimm_1 : wimm_2),
		   .wrrftag((we1 && (waddr1 == 1)) ? wrrftag_1 : wrrftag_2),
		   .wdstval((we1 && (waddr1 == 1)) ? wdstval_1 : wdstval_2),
		   .wsrc_a((we1 && (waddr1 == 1)) ? wsrc_a_1 : wsrc_a_2),
		   .wsrc_b((we1 && (waddr1 == 1)) ? wsrc_b_1 : wsrc_b_2),
		   .walu_op((we1 && (waddr1 == 1)) ? walu_op_1 : walu_op_2),
		   .wspectag((we1 && (waddr1 == 1)) ? wspectag_1 : wspectag_2),
		   .we((we1 && (waddr1 == 1)) || (we2 && (waddr2 == 1))),
		   .ex_src1(ex_src1_1),
		   .ex_src2(ex_src2_1),
		   .ready(ready_1),
		   .pc(pc_1),
		   .imm(imm_1),
		   .rrftag(rrftag_1),
		   .dstval(dstval_1),
		   .src_a(src_a_1),
		   .src_b(src_b_1),
		   .alu_op(alu_op_1),
		   .spectag(spectag_1),
		   .exrslt1(exrslt1),
		   .exdst1(exdst1),
		   .kill_spec1(kill_spec1),
		   .exrslt2(exrslt2),
		   .exdst2(exdst2),
		   .kill_spec2(kill_spec2),
		   .exrslt3(exrslt3),
		   .exdst3(exdst3),
		   .kill_spec3(kill_spec3),
		   .exrslt4(exrslt4),
		   .exdst4(exdst4),
		   .kill_spec4(kill_spec4),
		   .exrslt5(exrslt5),
		   .exdst5(exdst5),
		   .kill_spec5(kill_spec5)
		   );

   rs_alu_ent ent2(
		   .clk(clk),
		   .reset(reset),		   
		   .busy(busyvec[2]),
		   .wpc((we1 && (waddr1 == 2)) ? wpc_1 : wpc_2),
		   .wsrc1((we1 && (waddr1 == 2)) ? wsrc1_1 : wsrc1_2),
		   .wsrc2((we1 && (waddr1 == 2)) ? wsrc2_1 : wsrc2_2),
		   .wvalid1((we1 && (waddr1 == 2)) ? wvalid1_1 : wvalid1_2),
		   .wvalid2((we1 && (waddr1 == 2)) ? wvalid2_1 : wvalid2_2),
		   .wimm((we1 && (waddr1 == 2)) ? wimm_1 : wimm_2),
		   .wrrftag((we1 && (waddr1 == 2)) ? wrrftag_1 : wrrftag_2),
		   .wdstval((we1 && (waddr1 == 2)) ? wdstval_1 : wdstval_2),
		   .wsrc_a((we1 && (waddr1 == 2)) ? wsrc_a_1 : wsrc_a_2),
		   .wsrc_b((we1 && (waddr1 == 2)) ? wsrc_b_1 : wsrc_b_2),
		   .walu_op((we1 && (waddr1 == 2)) ? walu_op_1 : walu_op_2),
		   .wspectag((we1 && (waddr1 == 2)) ? wspectag_1 : wspectag_2),
		   .we((we1 && (waddr1 == 2)) || (we2 && (waddr2 == 2))),
		   .ex_src1(ex_src1_2),
		   .ex_src2(ex_src2_2),
		   .ready(ready_2),
		   .pc(pc_2),
		   .imm(imm_2),
		   .rrftag(rrftag_2),
		   .dstval(dstval_2),
		   .src_a(src_a_2),
		   .src_b(src_b_2),
		   .alu_op(alu_op_2),
		   .spectag(spectag_2),
		   .exrslt1(exrslt1),
		   .exdst1(exdst1),
		   .kill_spec1(kill_spec1),
		   .exrslt2(exrslt2),
		   .exdst2(exdst2),
		   .kill_spec2(kill_spec2),
		   .exrslt3(exrslt3),
		   .exdst3(exdst3),
		   .kill_spec3(kill_spec3),
		   .exrslt4(exrslt4),
		   .exdst4(exdst4),
		   .kill_spec4(kill_spec4),
		   .exrslt5(exrslt5),
		   .exdst5(exdst5),
		   .kill_spec5(kill_spec5)
		   );

   rs_alu_ent ent3(
		   .clk(clk),
		   .reset(reset),		   
		   .busy(busyvec[3]),
		   .wpc((we1 && (waddr1 == 3)) ? wpc_1 : wpc_2),
		   .wsrc1((we1 && (waddr1 == 3)) ? wsrc1_1 : wsrc1_2),
		   .wsrc2((we1 && (waddr1 == 3)) ? wsrc2_1 : wsrc2_2),
		   .wvalid1((we1 && (waddr1 == 3)) ? wvalid1_1 : wvalid1_2),
		   .wvalid2((we1 && (waddr1 == 3)) ? wvalid2_1 : wvalid2_2),
		   .wimm((we1 && (waddr1 == 3)) ? wimm_1 : wimm_2),
		   .wrrftag((we1 && (waddr1 == 3)) ? wrrftag_1 : wrrftag_2),
		   .wdstval((we1 && (waddr1 == 3)) ? wdstval_1 : wdstval_2),
		   .wsrc_a((we1 && (waddr1 == 3)) ? wsrc_a_1 : wsrc_a_2),
		   .wsrc_b((we1 && (waddr1 == 3)) ? wsrc_b_1 : wsrc_b_2),
		   .walu_op((we1 && (waddr1 == 3)) ? walu_op_1 : walu_op_2),
		   .wspectag((we1 && (waddr1 == 3)) ? wspectag_1 : wspectag_2),
		   .we((we1 && (waddr1 == 3)) || (we2 && (waddr2 == 3))),
		   .ex_src1(ex_src1_3),
		   .ex_src2(ex_src2_3),
		   .ready(ready_3),
		   .pc(pc_3),
		   .imm(imm_3),
		   .rrftag(rrftag_3),
		   .dstval(dstval_3),
		   .src_a(src_a_3),
		   .src_b(src_b_3),
		   .alu_op(alu_op_3),
		   .spectag(spectag_3),
		   .exrslt1(exrslt1),
		   .exdst1(exdst1),
		   .kill_spec1(kill_spec1),
		   .exrslt2(exrslt2),
		   .exdst2(exdst2),
		   .kill_spec2(kill_spec2),
		   .exrslt3(exrslt3),
		   .exdst3(exdst3),
		   .kill_spec3(kill_spec3),
		   .exrslt4(exrslt4),
		   .exdst4(exdst4),
		   .kill_spec4(kill_spec4),
		   .exrslt5(exrslt5),
		   .exdst5(exdst5),
		   .kill_spec5(kill_spec5)
		   );

   rs_alu_ent ent4(
		   .clk(clk),
		   .reset(reset),		   		   
		   .busy(busyvec[4]),
		   .wpc((we1 && (waddr1 == 4)) ? wpc_1 : wpc_2),
		   .wsrc1((we1 && (waddr1 == 4)) ? wsrc1_1 : wsrc1_2),
		   .wsrc2((we1 && (waddr1 == 4)) ? wsrc2_1 : wsrc2_2),
		   .wvalid1((we1 && (waddr1 == 4)) ? wvalid1_1 : wvalid1_2),
		   .wvalid2((we1 && (waddr1 == 4)) ? wvalid2_1 : wvalid2_2),
		   .wimm((we1 && (waddr1 == 4)) ? wimm_1 : wimm_2),
		   .wrrftag((we1 && (waddr1 == 4)) ? wrrftag_1 : wrrftag_2),
		   .wdstval((we1 && (waddr1 == 4)) ? wdstval_1 : wdstval_2),
		   .wsrc_a((we1 && (waddr1 == 4)) ? wsrc_a_1 : wsrc_a_2),
		   .wsrc_b((we1 && (waddr1 == 4)) ? wsrc_b_1 : wsrc_b_2),
		   .walu_op((we1 && (waddr1 == 4)) ? walu_op_1 : walu_op_2),
		   .wspectag((we1 && (waddr1 == 4)) ? wspectag_1 : wspectag_2),
		   .we((we1 && (waddr1 == 4)) || (we2 && (waddr2 == 4))),
		   .ex_src1(ex_src1_4),
		   .ex_src2(ex_src2_4),
		   .ready(ready_4),
		   .pc(pc_4),
		   .imm(imm_4),
		   .rrftag(rrftag_4),
		   .dstval(dstval_4),
		   .src_a(src_a_4),
		   .src_b(src_b_4),
		   .alu_op(alu_op_4),
		   .spectag(spectag_4),
		   .exrslt1(exrslt1),
		   .exdst1(exdst1),
		   .kill_spec1(kill_spec1),
		   .exrslt2(exrslt2),
		   .exdst2(exdst2),
		   .kill_spec2(kill_spec2),
		   .exrslt3(exrslt3),
		   .exdst3(exdst3),
		   .kill_spec3(kill_spec3),
		   .exrslt4(exrslt4),
		   .exdst4(exdst4),
		   .kill_spec4(kill_spec4),
		   .exrslt5(exrslt5),
		   .exdst5(exdst5),
		   .kill_spec5(kill_spec5)
		   );

   rs_alu_ent ent5(
		   .clk(clk),
		   .reset(reset),		   
		   .busy(busyvec[5]),
		   .wpc((we1 && (waddr1 == 5)) ? wpc_1 : wpc_2),
		   .wsrc1((we1 && (waddr1 == 5)) ? wsrc1_1 : wsrc1_2),
		   .wsrc2((we1 && (waddr1 == 5)) ? wsrc2_1 : wsrc2_2),
		   .wvalid1((we1 && (waddr1 == 5)) ? wvalid1_1 : wvalid1_2),
		   .wvalid2((we1 && (waddr1 == 5)) ? wvalid2_1 : wvalid2_2),
		   .wimm((we1 && (waddr1 == 5)) ? wimm_1 : wimm_2),
		   .wrrftag((we1 && (waddr1 == 5)) ? wrrftag_1 : wrrftag_2),
		   .wdstval((we1 && (waddr1 == 5)) ? wdstval_1 : wdstval_2),
		   .wsrc_a((we1 && (waddr1 == 5)) ? wsrc_a_1 : wsrc_a_2),
		   .wsrc_b((we1 && (waddr1 == 5)) ? wsrc_b_1 : wsrc_b_2),
		   .walu_op((we1 && (waddr1 == 5)) ? walu_op_1 : walu_op_2),
		   .wspectag((we1 && (waddr1 == 5)) ? wspectag_1 : wspectag_2),
		   .we((we1 && (waddr1 == 5)) || (we2 && (waddr2 == 5))),
		   .ex_src1(ex_src1_5),
		   .ex_src2(ex_src2_5),
		   .ready(ready_5),
		   .pc(pc_5),
		   .imm(imm_5),
		   .rrftag(rrftag_5),
		   .dstval(dstval_5),
		   .src_a(src_a_5),
		   .src_b(src_b_5),
		   .alu_op(alu_op_5),
		   .spectag(spectag_5),
		   .exrslt1(exrslt1),
		   .exdst1(exdst1),
		   .kill_spec1(kill_spec1),
		   .exrslt2(exrslt2),
		   .exdst2(exdst2),
		   .kill_spec2(kill_spec2),
		   .exrslt3(exrslt3),
		   .exdst3(exdst3),
		   .kill_spec3(kill_spec3),
		   .exrslt4(exrslt4),
		   .exdst4(exdst4),
		   .kill_spec4(kill_spec4),
		   .exrslt5(exrslt5),
		   .exdst5(exdst5),
		   .kill_spec5(kill_spec5)
		   );

   rs_alu_ent ent6(
		   .clk(clk),
		   .reset(reset),		   
		   .busy(busyvec[6]),
		   .wpc((we1 && (waddr1 == 6)) ? wpc_1 : wpc_2),
		   .wsrc1((we1 && (waddr1 == 6)) ? wsrc1_1 : wsrc1_2),
		   .wsrc2((we1 && (waddr1 == 6)) ? wsrc2_1 : wsrc2_2),
		   .wvalid1((we1 && (waddr1 == 6)) ? wvalid1_1 : wvalid1_2),
		   .wvalid2((we1 && (waddr1 == 6)) ? wvalid2_1 : wvalid2_2),
		   .wimm((we1 && (waddr1 == 6)) ? wimm_1 : wimm_2),
		   .wrrftag((we1 && (waddr1 == 6)) ? wrrftag_1 : wrrftag_2),
		   .wdstval((we1 && (waddr1 == 6)) ? wdstval_1 : wdstval_2),
		   .wsrc_a((we1 && (waddr1 == 6)) ? wsrc_a_1 : wsrc_a_2),
		   .wsrc_b((we1 && (waddr1 == 6)) ? wsrc_b_1 : wsrc_b_2),
		   .walu_op((we1 && (waddr1 == 6)) ? walu_op_1 : walu_op_2),
		   .wspectag((we1 && (waddr1 == 6)) ? wspectag_1 : wspectag_2),
		   .we((we1 && (waddr1 == 6)) || (we2 && (waddr2 == 6))),
		   .ex_src1(ex_src1_6),
		   .ex_src2(ex_src2_6),
		   .ready(ready_6),
		   .pc(pc_6),
		   .imm(imm_6),
		   .rrftag(rrftag_6),
		   .dstval(dstval_6),
		   .src_a(src_a_6),
		   .src_b(src_b_6),
		   .alu_op(alu_op_6),
		   .spectag(spectag_6),
		   .exrslt1(exrslt1),
		   .exdst1(exdst1),
		   .kill_spec1(kill_spec1),
		   .exrslt2(exrslt2),
		   .exdst2(exdst2),
		   .kill_spec2(kill_spec2),
		   .exrslt3(exrslt3),
		   .exdst3(exdst3),
		   .kill_spec3(kill_spec3),
		   .exrslt4(exrslt4),
		   .exdst4(exdst4),
		   .kill_spec4(kill_spec4),
		   .exrslt5(exrslt5),
		   .exdst5(exdst5),
		   .kill_spec5(kill_spec5)
		   );

   rs_alu_ent ent7(
		   .clk(clk),
		   .reset(reset),		   
		   .busy(busyvec[7]),
		   .wpc((we1 && (waddr1 == 7)) ? wpc_1 : wpc_2),
		   .wsrc1((we1 && (waddr1 == 7)) ? wsrc1_1 : wsrc1_2),
		   .wsrc2((we1 && (waddr1 == 7)) ? wsrc2_1 : wsrc2_2),
		   .wvalid1((we1 && (waddr1 == 7)) ? wvalid1_1 : wvalid1_2),
		   .wvalid2((we1 && (waddr1 == 7)) ? wvalid2_1 : wvalid2_2),
		   .wimm((we1 && (waddr1 == 7)) ? wimm_1 : wimm_2),
		   .wrrftag((we1 && (waddr1 == 7)) ? wrrftag_1 : wrrftag_2),
		   .wdstval((we1 && (waddr1 == 7)) ? wdstval_1 : wdstval_2),
		   .wsrc_a((we1 && (waddr1 == 7)) ? wsrc_a_1 : wsrc_a_2),
		   .wsrc_b((we1 && (waddr1 == 7)) ? wsrc_b_1 : wsrc_b_2),
		   .walu_op((we1 && (waddr1 == 7)) ? walu_op_1 : walu_op_2),
		   .wspectag((we1 && (waddr1 == 7)) ? wspectag_1 : wspectag_2),
		   .we((we1 && (waddr1 == 7)) || (we2 && (waddr2 == 7))),
		   .ex_src1(ex_src1_7),
		   .ex_src2(ex_src2_7),
		   .ready(ready_7),
		   .pc(pc_7),
		   .imm(imm_7),
		   .rrftag(rrftag_7),
		   .dstval(dstval_7),
		   .src_a(src_a_7),
		   .src_b(src_b_7),
		   .alu_op(alu_op_7),
		   .spectag(spectag_7),
		   .exrslt1(exrslt1),
		   .exdst1(exdst1),
		   .kill_spec1(kill_spec1),
		   .exrslt2(exrslt2),
		   .exdst2(exdst2),
		   .kill_spec2(kill_spec2),
		   .exrslt3(exrslt3),
		   .exdst3(exdst3),
		   .kill_spec3(kill_spec3),
		   .exrslt4(exrslt4),
		   .exdst4(exdst4),
		   .kill_spec4(kill_spec4),
		   .exrslt5(exrslt5),
		   .exdst5(exdst5),
		   .kill_spec5(kill_spec5)
		   );
   
   assign ex_src1 = (issueaddr == 0) ? ex_src1_0 :
		    (issueaddr == 1) ? ex_src1_1 :
		    (issueaddr == 2) ? ex_src1_2 :
		    (issueaddr == 3) ? ex_src1_3 :
		    (issueaddr == 4) ? ex_src1_4 :
		    (issueaddr == 5) ? ex_src1_5 :
		    (issueaddr == 6) ? ex_src1_6 : ex_src1_7;

   assign ex_src2 = (issueaddr == 0) ? ex_src2_0 :
		    (issueaddr == 1) ? ex_src2_1 :
		    (issueaddr == 2) ? ex_src2_2 :
		    (issueaddr == 3) ? ex_src2_3 :
		    (issueaddr == 4) ? ex_src2_4 :
		    (issueaddr == 5) ? ex_src2_5 :
		    (issueaddr == 6) ? ex_src2_6 : ex_src2_7;

   assign pc = (issueaddr == 0) ? pc_0 :
	       (issueaddr == 1) ? pc_1 :
	       (issueaddr == 2) ? pc_2 :
	       (issueaddr == 3) ? pc_3 :
	       (issueaddr == 4) ? pc_4 :
	       (issueaddr == 5) ? pc_5 :
	       (issueaddr == 6) ? pc_6 : pc_7;
   
   assign imm = (issueaddr == 0) ? imm_0 :
		(issueaddr == 1) ? imm_1 :
		(issueaddr == 2) ? imm_2 :
		(issueaddr == 3) ? imm_3 :
		(issueaddr == 4) ? imm_4 :
		(issueaddr == 5) ? imm_5 :
		(issueaddr == 6) ? imm_6 : imm_7;
   
   assign rrftag = (issueaddr == 0) ? rrftag_0 :
		   (issueaddr == 1) ? rrftag_1 :
		   (issueaddr == 2) ? rrftag_2 :
		   (issueaddr == 3) ? rrftag_3 :
		   (issueaddr == 4) ? rrftag_4 :
		   (issueaddr == 5) ? rrftag_5 :
		   (issueaddr == 6) ? rrftag_6 : rrftag_7;
   
   assign dstval = (issueaddr == 0) ? dstval_0 :
		   (issueaddr == 1) ? dstval_1 :
		   (issueaddr == 2) ? dstval_2 :
		   (issueaddr == 3) ? dstval_3 :
		   (issueaddr == 4) ? dstval_4 :
		   (issueaddr == 5) ? dstval_5 :
		   (issueaddr == 6) ? dstval_6 : dstval_7;
   
   assign src_a = (issueaddr == 0) ? src_a_0 :
		  (issueaddr == 1) ? src_a_1 :
		  (issueaddr == 2) ? src_a_2 :
		  (issueaddr == 3) ? src_a_3 :
		  (issueaddr == 4) ? src_a_4 :
		  (issueaddr == 5) ? src_a_5 :
		  (issueaddr == 6) ? src_a_6 : src_a_7;
   
   assign src_b = (issueaddr == 0) ? src_b_0 :
		  (issueaddr == 1) ? src_b_1 :
		  (issueaddr == 2) ? src_b_2 :
		  (issueaddr == 3) ? src_b_3 :
		  (issueaddr == 4) ? src_b_4 :
		  (issueaddr == 5) ? src_b_5 :
		  (issueaddr == 6) ? src_b_6 : src_b_7;
   
   assign alu_op = (issueaddr == 0) ? alu_op_0 :
		   (issueaddr == 1) ? alu_op_1 :
		   (issueaddr == 2) ? alu_op_2 :
		   (issueaddr == 3) ? alu_op_3 :
		   (issueaddr == 4) ? alu_op_4 :
		   (issueaddr == 5) ? alu_op_5 :
		   (issueaddr == 6) ? alu_op_6 : alu_op_7;
   
   assign spectag = (issueaddr == 0) ? spectag_0 :
		    (issueaddr == 1) ? spectag_1 :
		    (issueaddr == 2) ? spectag_2 :
		    (issueaddr == 3) ? spectag_3 :
		    (issueaddr == 4) ? spectag_4 :
		    (issueaddr == 5) ? spectag_5 :
		    (issueaddr == 6) ? spectag_6 : spectag_7;

   
endmodule // rs_alu
`default_nettype wire
`include "constants.vh"
`include "alu_ops.vh"
`include "rv32_opcodes.vh"
`default_nettype none
module rs_branch_ent
  (
   //Memory
   input wire 			  clk,
   input wire 			  reset,
   input wire 			  busy,
   input wire [`ADDR_LEN-1:0] 	  wpc,
   input wire [`DATA_LEN-1:0] 	  wsrc1,
   input wire [`DATA_LEN-1:0] 	  wsrc2,
   input wire 			  wvalid1,
   input wire 			  wvalid2,
   input wire [`DATA_LEN-1:0] 	  wimm,
   input wire [`RRF_SEL-1:0] 	  wrrftag,
   input wire 			  wdstval,
   input wire [`ALU_OP_WIDTH-1:0] walu_op,
   input wire [`SPECTAG_LEN-1:0]  wspectag,
   input wire [`GSH_BHR_LEN-1:0]  wbhr,
   input wire 			  wprcond,
   input wire [`ADDR_LEN-1:0] 	  wpraddr,
   input wire [6:0] 		  wopcode,
   input wire 			  we,
   output wire [`DATA_LEN-1:0] 	  ex_src1,
   output wire [`DATA_LEN-1:0] 	  ex_src2,
   output wire 			  ready,
   output reg [`ADDR_LEN-1:0] 	  pc,
   output reg [`DATA_LEN-1:0] 	  imm,
   output reg [`RRF_SEL-1:0] 	  rrftag,
   output reg 			  dstval,
   output reg [`ALU_OP_WIDTH-1:0] alu_op,
   output reg [`SPECTAG_LEN-1:0]  spectag,
   output reg [`GSH_BHR_LEN-1:0]  bhr,
   output reg 			  prcond,
   output reg [`ADDR_LEN-1:0] 	  praddr,
   output reg [6:0] 		  opcode,
   //EXRSLT
   input wire [`DATA_LEN-1:0] 	  exrslt1,
   input wire [`RRF_SEL-1:0] 	  exdst1,
   input wire 			  kill_spec1,
   input wire [`DATA_LEN-1:0] 	  exrslt2,
   input wire [`RRF_SEL-1:0] 	  exdst2,
   input wire 			  kill_spec2,
   input wire [`DATA_LEN-1:0] 	  exrslt3,
   input wire [`RRF_SEL-1:0] 	  exdst3,
   input wire 			  kill_spec3,
   input wire [`DATA_LEN-1:0] 	  exrslt4,
   input wire [`RRF_SEL-1:0] 	  exdst4,
   input wire 			  kill_spec4,
   input wire [`DATA_LEN-1:0] 	  exrslt5,
   input wire [`RRF_SEL-1:0] 	  exdst5,
   input wire 			  kill_spec5
   );

   reg [`DATA_LEN-1:0] 		  src1;
   reg [`DATA_LEN-1:0] 		  src2;
   reg 				  valid1;
   reg 				  valid2;

   wire [`DATA_LEN-1:0] 	  nextsrc1;
   wire [`DATA_LEN-1:0] 	  nextsrc2;   
   wire 			  nextvalid1;
   wire 			  nextvalid2;
   
   assign ready = busy & valid1 & valid2;
   assign ex_src1 = ~valid1 & nextvalid1 ?
		    nextsrc1 : src1;
   assign ex_src2 = ~valid2 & nextvalid2 ?
		    nextsrc2 : src2;
   
   always @ (posedge clk) begin
      if (reset) begin
	 pc <= 0;
	 imm <= 0;
	 rrftag <= 0;
	 dstval <= 0;
	 alu_op <= 0;
	 spectag <= 0;
	 bhr <= 0;
	 prcond <= 0;
	 praddr <= 0;
	 opcode <= 0;
	 
	 src1 <= 0;
	 src2 <= 0;
	 valid1 <= 0;
	 valid2 <= 0;
      end else if (we) begin
	 pc <= wpc;
	 imm <= wimm;
	 rrftag <= wrrftag;
	 dstval <= wdstval;
	 alu_op <= walu_op;
	 spectag <= wspectag;
	 bhr <= wbhr;
	 prcond <= wprcond;
	 praddr <= wpraddr;
	 opcode <= wopcode;

	 src1 <= wsrc1;
	 src2 <= wsrc2;
	 valid1 <= wvalid1;
	 valid2 <= wvalid2;
      end else begin // if (we)
	 src1 <= nextsrc1;
	 src2 <= nextsrc2;
	 valid1 <= nextvalid1;
	 valid2 <= nextvalid2;
      end
   end
   
   src_manager srcmng1(
		       .opr(src1),
		       .opr_rdy(valid1),
		       .exrslt1(exrslt1),
		       .exdst1(exdst1),
		       .kill_spec1(kill_spec1),
		       .exrslt2(exrslt2),
		       .exdst2(exdst2),
		       .kill_spec2(kill_spec2),
		       .exrslt3(exrslt3),
		       .exdst3(exdst3),
		       .kill_spec3(kill_spec3),
		       .exrslt4(exrslt4),
		       .exdst4(exdst4),
		       .kill_spec4(kill_spec4),
		       .exrslt5(exrslt5),
		       .exdst5(exdst5),
		       .kill_spec5(kill_spec5),
		       .src(nextsrc1),
		       .resolved(nextvalid1)
		       );

   src_manager srcmng2(
		       .opr(src2),
		       .opr_rdy(valid2),
		       .exrslt1(exrslt1),
		       .exdst1(exdst1),
		       .kill_spec1(kill_spec1),
		       .exrslt2(exrslt2),
		       .exdst2(exdst2),
		       .kill_spec2(kill_spec2),
		       .exrslt3(exrslt3),
		       .exdst3(exdst3),
		       .kill_spec3(kill_spec3),
		       .exrslt4(exrslt4),
		       .exdst4(exdst4),
		       .kill_spec4(kill_spec4),
		       .exrslt5(exrslt5),
		       .exdst5(exdst5),
		       .kill_spec5(kill_spec5),
		       .src(nextsrc2),
		       .resolved(nextvalid2)
		       );
   
endmodule // rs_branch



module rs_branch
  (
   //System
   input wire 			     clk,
   input wire 			     reset,
   output reg [`BRANCH_ENT_NUM-1:0]  busyvec,
   input wire 			     prmiss,
   input wire 			     prsuccess,
   input wire [`SPECTAG_LEN-1:0]     prtag,
   input wire [`SPECTAG_LEN-1:0]     specfixtag,
   output wire [`BRANCH_ENT_NUM-1:0] prbusyvec_next,
   //WriteSignal
   input wire 			     clearbusy, //Issue 
   input wire [`BRANCH_ENT_SEL-1:0]  issueaddr, //= raddr, clsbsyadr
   input wire 			     we1, //alloc1
   input wire 			     we2, //alloc2
   input wire [`BRANCH_ENT_SEL-1:0]  waddr1, //allocent1
   input wire [`BRANCH_ENT_SEL-1:0]  waddr2, //allocent2
   //WriteSignal1
   input wire [`ADDR_LEN-1:0] 	     wpc_1,
   input wire [`DATA_LEN-1:0] 	     wsrc1_1,
   input wire [`DATA_LEN-1:0] 	     wsrc2_1,
   input wire 			     wvalid1_1,
   input wire 			     wvalid2_1,
   input wire [`DATA_LEN-1:0] 	     wimm_1,
   input wire [`RRF_SEL-1:0] 	     wrrftag_1,
   input wire 			     wdstval_1,
   input wire [`ALU_OP_WIDTH-1:0]    walu_op_1,
   input wire [`SPECTAG_LEN-1:0]     wspectag_1,
   input wire 			     wspecbit_1,
   input wire [`GSH_BHR_LEN-1:0]     wbhr_1,
   input wire 			     wprcond_1,
   input wire [`ADDR_LEN-1:0] 	     wpraddr_1,
   input wire [6:0] 		     wopcode_1,

   //WriteSignal2
   input wire [`ADDR_LEN-1:0] 	     wpc_2,
   input wire [`DATA_LEN-1:0] 	     wsrc1_2,
   input wire [`DATA_LEN-1:0] 	     wsrc2_2,
   input wire 			     wvalid1_2,
   input wire 			     wvalid2_2,
   input wire [`DATA_LEN-1:0] 	     wimm_2,
   input wire [`RRF_SEL-1:0] 	     wrrftag_2,
   input wire 			     wdstval_2,
   input wire [`ALU_OP_WIDTH-1:0]    walu_op_2,
   input wire [`SPECTAG_LEN-1:0]     wspectag_2,
   input wire 			     wspecbit_2,
   input wire [`GSH_BHR_LEN-1:0]     wbhr_2,
   input wire 			     wprcond_2,
   input wire [`ADDR_LEN-1:0] 	     wpraddr_2,
   input wire [6:0] 		     wopcode_2,

   //ReadSignal
   output wire [`DATA_LEN-1:0] 	     ex_src1,
   output wire [`DATA_LEN-1:0] 	     ex_src2,
   output wire [`BRANCH_ENT_NUM-1:0] ready,
   output wire [`ADDR_LEN-1:0] 	     pc,
   output wire [`DATA_LEN-1:0] 	     imm,
   output wire [`RRF_SEL-1:0] 	     rrftag,
   output wire 			     dstval,
   output wire [`ALU_OP_WIDTH-1:0]   alu_op,
   output wire [`SPECTAG_LEN-1:0]    spectag,
   output wire 			     specbit,
   output wire [`GSH_BHR_LEN-1:0]    bhr,
   output wire 			     prcond,
   output wire [`ADDR_LEN-1:0] 	     praddr,
   output wire [6:0] 		     opcode,
  
   //EXRSLT
   input wire [`DATA_LEN-1:0] 	     exrslt1,
   input wire [`RRF_SEL-1:0] 	     exdst1,
   input wire 			     kill_spec1,
   input wire [`DATA_LEN-1:0] 	     exrslt2,
   input wire [`RRF_SEL-1:0] 	     exdst2,
   input wire 			     kill_spec2,
   input wire [`DATA_LEN-1:0] 	     exrslt3,
   input wire [`RRF_SEL-1:0] 	     exdst3,
   input wire 			     kill_spec3,
   input wire [`DATA_LEN-1:0] 	     exrslt4,
   input wire [`RRF_SEL-1:0] 	     exdst4,
   input wire 			     kill_spec4,
   input wire [`DATA_LEN-1:0] 	     exrslt5,
   input wire [`RRF_SEL-1:0] 	     exdst5,
   input wire 			     kill_spec5
   );

   //_0
   wire [`DATA_LEN-1:0] 	     ex_src1_0;
   wire [`DATA_LEN-1:0] 	     ex_src2_0;
   wire 			     ready_0;
   wire [`ADDR_LEN-1:0] 	     pc_0;
   wire [`DATA_LEN-1:0] 	     imm_0;
   wire [`RRF_SEL-1:0] 		     rrftag_0;
   wire 			     dstval_0;
   wire [`ALU_OP_WIDTH-1:0] 	     alu_op_0;
   wire [`SPECTAG_LEN-1:0] 	     spectag_0;
   wire [`GSH_BHR_LEN-1:0] 	     bhr_0;
   wire 			     prcond_0;
   wire [`ADDR_LEN-1:0] 	     praddr_0;
   wire [6:0] 			     opcode_0;
   //_1
   wire [`DATA_LEN-1:0] 	     ex_src1_1;
   wire [`DATA_LEN-1:0] 	     ex_src2_1;
   wire 			     ready_1;
   wire [`ADDR_LEN-1:0] 	     pc_1;
   wire [`DATA_LEN-1:0] 	     imm_1;
   wire [`RRF_SEL-1:0] 		     rrftag_1;
   wire 			     dstval_1;
   wire [`ALU_OP_WIDTH-1:0] 	     alu_op_1;
   wire [`SPECTAG_LEN-1:0] 	     spectag_1;
   wire [`GSH_BHR_LEN-1:0] 	     bhr_1;
   wire 			     prcond_1;
   wire [`ADDR_LEN-1:0] 	     praddr_1;
   wire [6:0] 			     opcode_1;
   //_2
   wire [`DATA_LEN-1:0] 	     ex_src1_2;
   wire [`DATA_LEN-1:0] 	     ex_src2_2;
   wire 			     ready_2;
   wire [`ADDR_LEN-1:0] 	     pc_2;
   wire [`DATA_LEN-1:0] 	     imm_2;
   wire [`RRF_SEL-1:0] 		     rrftag_2;
   wire 			     dstval_2;
   wire [`ALU_OP_WIDTH-1:0] 	     alu_op_2;
   wire [`SPECTAG_LEN-1:0] 	     spectag_2;
   wire [`GSH_BHR_LEN-1:0] 	     bhr_2;
   wire 			     prcond_2;
   wire [`ADDR_LEN-1:0] 	     praddr_2;
   wire [6:0] 			     opcode_2;
   //_3
   wire [`DATA_LEN-1:0] 	     ex_src1_3;
   wire [`DATA_LEN-1:0] 	     ex_src2_3;
   wire 			     ready_3;
   wire [`ADDR_LEN-1:0] 	     pc_3;
   wire [`DATA_LEN-1:0] 	     imm_3;
   wire [`RRF_SEL-1:0] 		     rrftag_3;
   wire 			     dstval_3;
   wire [`ALU_OP_WIDTH-1:0] 	     alu_op_3;
   wire [`SPECTAG_LEN-1:0] 	     spectag_3;
   wire [`GSH_BHR_LEN-1:0] 	     bhr_3;
   wire 			     prcond_3;
   wire [`ADDR_LEN-1:0] 	     praddr_3;
   wire [6:0] 			     opcode_3;
   
   reg [`BRANCH_ENT_NUM-1:0] 	     specbitvec;

   wire [`BRANCH_ENT_NUM-1:0] 	     inv_vector =
				     {(spectag_3 & specfixtag) == 0 ? 1'b1 : 1'b0,
				      (spectag_2 & specfixtag) == 0 ? 1'b1 : 1'b0,
				      (spectag_1 & specfixtag) == 0 ? 1'b1 : 1'b0,
				      (spectag_0 & specfixtag) == 0 ? 1'b1 : 1'b0};

   wire [`BRANCH_ENT_NUM-1:0] 	     inv_vector_spec =
				     {(spectag_3 == prtag) ? 1'b0 : 1'b1,
				      (spectag_2 == prtag) ? 1'b0 : 1'b1,
				      (spectag_1 == prtag) ? 1'b0 : 1'b1,
				      (spectag_0 == prtag) ? 1'b0 : 1'b1};

   wire [`BRANCH_ENT_NUM-1:0] 	     specbitvec_next =
				     (inv_vector_spec & specbitvec);
   /* |
    (we1 & wspecbit_1 ? (`BRANCH_ENT_SEL'b1 << waddr1) : 0) |
    (we2 & wspecbit_2 ? (`BRANCH_ENT_SEL'b1 << waddr2) : 0);
    */
   assign specbit = prsuccess ? 
		    specbitvec_next[issueaddr] : specbitvec[issueaddr];
   
   assign ready = {ready_3, ready_2, ready_1, ready_0};
   assign prbusyvec_next = inv_vector & busyvec;
   
   always @ (posedge clk) begin
      if (reset) begin
	 busyvec <= 0;
	 specbitvec <= 0;
      end else begin
	 if (prmiss) begin
	    busyvec <= prbusyvec_next;
	    specbitvec <= 0;
	 end else if (prsuccess) begin
	    specbitvec <= specbitvec_next;
	    /*
	     if (we1) begin
	     busyvec[waddr1] <= 1'b1;
	    end
	     if (we2) begin
	     busyvec[waddr2] <= 1'b1;
	    end
	     */
	    if (clearbusy) begin
	       busyvec[issueaddr] <= 1'b0;
	    end
	 end else begin
	    if (we1) begin
	       busyvec[waddr1] <= 1'b1;
	       specbitvec[waddr1] <= wspecbit_1;
	    end
	    if (we2) begin
	       busyvec[waddr2] <= 1'b1;
	       specbitvec[waddr2] <= wspecbit_2;
	    end
	    if (clearbusy) begin
	       busyvec[issueaddr] <= 1'b0;
	    end
	 end
      end
   end

   rs_branch_ent ent0(
		      .clk(clk),
		      .reset(reset),		      
		      .busy(busyvec[0]),
		      .wpc((we1 && (waddr1 == 0)) ? wpc_1 : wpc_2),
		      .wsrc1((we1 && (waddr1 == 0)) ? wsrc1_1 : wsrc1_2),
		      .wsrc2((we1 && (waddr1 == 0)) ? wsrc2_1 : wsrc2_2),
		      .wvalid1((we1 && (waddr1 == 0)) ? wvalid1_1 : wvalid1_2),
		      .wvalid2((we1 && (waddr1 == 0)) ? wvalid2_1 : wvalid2_2),
		      .wimm((we1 && (waddr1 == 0)) ? wimm_1 : wimm_2),
		      .wrrftag((we1 && (waddr1 == 0)) ? wrrftag_1 : wrrftag_2),
		      .wdstval((we1 && (waddr1 == 0)) ? wdstval_1 : wdstval_2),
		      .walu_op((we1 && (waddr1 == 0)) ? walu_op_1 : walu_op_2),
		      .wspectag((we1 && (waddr1 == 0)) ? wspectag_1 : wspectag_2),
		      .wbhr((we1 && (waddr1 == 0)) ? wbhr_1 : wbhr_2),
		      .wpraddr((we1 && (waddr1 == 0)) ? wpraddr_1 : wpraddr_2),
		      .wprcond((we1 && (waddr1 == 0)) ? wprcond_1 : wprcond_2),
		      .wopcode((we1 && (waddr1 == 0)) ? wopcode_1 : wopcode_2),
		      .we((we1 && (waddr1 == 0)) || (we2 && (waddr2 == 0))),
		      .ex_src1(ex_src1_0),
		      .ex_src2(ex_src2_0),
		      .ready(ready_0),
		      .pc(pc_0),
		      .imm(imm_0),
		      .rrftag(rrftag_0),
		      .dstval(dstval_0),
		      .alu_op(alu_op_0),
		      .spectag(spectag_0),
		      .bhr(bhr_0),
		      .prcond(prcond_0),
		      .praddr(praddr_0),
		      .opcode(opcode_0),
		      .exrslt1(exrslt1),
		      .exdst1(exdst1),
		      .kill_spec1(kill_spec1),
		      .exrslt2(exrslt2),
		      .exdst2(exdst2),
		      .kill_spec2(kill_spec2),
		      .exrslt3(exrslt3),
		      .exdst3(exdst3),
		      .kill_spec3(kill_spec3),
		      .exrslt4(exrslt4),
		      .exdst4(exdst4),
		      .kill_spec4(kill_spec4),
		      .exrslt5(exrslt5),
		      .exdst5(exdst5),
		      .kill_spec5(kill_spec5)
		      );

   rs_branch_ent ent1(
		      .clk(clk),
		      .reset(reset),		      		      
		      .busy(busyvec[1]),
		      .wpc((we1 && (waddr1 == 1)) ? wpc_1 : wpc_2),
		      .wsrc1((we1 && (waddr1 == 1)) ? wsrc1_1 : wsrc1_2),
		      .wsrc2((we1 && (waddr1 == 1)) ? wsrc2_1 : wsrc2_2),
		      .wvalid1((we1 && (waddr1 == 1)) ? wvalid1_1 : wvalid1_2),
		      .wvalid2((we1 && (waddr1 == 1)) ? wvalid2_1 : wvalid2_2),
		      .wimm((we1 && (waddr1 == 1)) ? wimm_1 : wimm_2),
		      .wrrftag((we1 && (waddr1 == 1)) ? wrrftag_1 : wrrftag_2),
		      .wdstval((we1 && (waddr1 == 1)) ? wdstval_1 : wdstval_2),
		      .walu_op((we1 && (waddr1 == 1)) ? walu_op_1 : walu_op_2),
		      .wspectag((we1 && (waddr1 == 1)) ? wspectag_1 : wspectag_2),
		      .wbhr((we1 && (waddr1 == 1)) ? wbhr_1 : wbhr_2),
		      .wpraddr((we1 && (waddr1 == 1)) ? wpraddr_1 : wpraddr_2),
		      .wprcond((we1 && (waddr1 == 1)) ? wprcond_1 : wprcond_2),
		      .wopcode((we1 && (waddr1 == 1)) ? wopcode_1 : wopcode_2),
		      .we((we1 && (waddr1 == 1)) || (we2 && (waddr2 == 1))),
		      .ex_src1(ex_src1_1),
		      .ex_src2(ex_src2_1),
		      .ready(ready_1),
		      .pc(pc_1),
		      .imm(imm_1),
		      .rrftag(rrftag_1),
		      .dstval(dstval_1),
		      .alu_op(alu_op_1),
		      .spectag(spectag_1),
		      .bhr(bhr_1),
		      .prcond(prcond_1),
		      .praddr(praddr_1),
		      .opcode(opcode_1),
		      .exrslt1(exrslt1),
		      .exdst1(exdst1),
		      .kill_spec1(kill_spec1),
		      .exrslt2(exrslt2),
		      .exdst2(exdst2),
		      .kill_spec2(kill_spec2),
		      .exrslt3(exrslt3),
		      .exdst3(exdst3),
		      .kill_spec3(kill_spec3),
		      .exrslt4(exrslt4),
		      .exdst4(exdst4),
		      .kill_spec4(kill_spec4),
		      .exrslt5(exrslt5),
		      .exdst5(exdst5),
		      .kill_spec5(kill_spec5)
		      );

   rs_branch_ent ent2(
		      .clk(clk),
		      .reset(reset),		      		      
		      .busy(busyvec[2]),
		      .wpc((we1 && (waddr1 == 2)) ? wpc_1 : wpc_2),
		      .wsrc1((we1 && (waddr1 == 2)) ? wsrc1_1 : wsrc1_2),
		      .wsrc2((we1 && (waddr1 == 2)) ? wsrc2_1 : wsrc2_2),
		      .wvalid1((we1 && (waddr1 == 2)) ? wvalid1_1 : wvalid1_2),
		      .wvalid2((we1 && (waddr1 == 2)) ? wvalid2_1 : wvalid2_2),
		      .wimm((we1 && (waddr1 == 2)) ? wimm_1 : wimm_2),
		      .wrrftag((we1 && (waddr1 == 2)) ? wrrftag_1 : wrrftag_2),
		      .wdstval((we1 && (waddr1 == 2)) ? wdstval_1 : wdstval_2),
		      .walu_op((we1 && (waddr1 == 2)) ? walu_op_1 : walu_op_2),
		      .wspectag((we1 && (waddr1 == 2)) ? wspectag_1 : wspectag_2),
		      .wbhr((we1 && (waddr1 == 2)) ? wbhr_1 : wbhr_2),
		      .wpraddr((we1 && (waddr1 == 2)) ? wpraddr_1 : wpraddr_2),
		      .wprcond((we1 && (waddr1 == 2)) ? wprcond_1 : wprcond_2),
		      .wopcode((we1 && (waddr1 == 2)) ? wopcode_1 : wopcode_2),
		      .we((we1 && (waddr1 == 2)) || (we2 && (waddr2 == 2))),
		      .ex_src1(ex_src1_2),
		      .ex_src2(ex_src2_2),
		      .ready(ready_2),
		      .pc(pc_2),
		      .imm(imm_2),
		      .rrftag(rrftag_2),
		      .dstval(dstval_2),
		      .alu_op(alu_op_2),
		      .spectag(spectag_2),
		      .bhr(bhr_2),
		      .prcond(prcond_2),
		      .praddr(praddr_2),
		      .opcode(opcode_2),
		      .exrslt1(exrslt1),
		      .exdst1(exdst1),
		      .kill_spec1(kill_spec1),
		      .exrslt2(exrslt2),
		      .exdst2(exdst2),
		      .kill_spec2(kill_spec2),
		      .exrslt3(exrslt3),
		      .exdst3(exdst3),
		      .kill_spec3(kill_spec3),
		      .exrslt4(exrslt4),
		      .exdst4(exdst4),
		      .kill_spec4(kill_spec4),
		      .exrslt5(exrslt5),
		      .exdst5(exdst5),
		      .kill_spec5(kill_spec5)
		      );

   rs_branch_ent ent3(
		      .clk(clk),
		      .reset(reset),		      		      
		      .busy(busyvec[3]),
		      .wpc((we1 && (waddr1 == 3)) ? wpc_1 : wpc_2),
		      .wsrc1((we1 && (waddr1 == 3)) ? wsrc1_1 : wsrc1_2),
		      .wsrc2((we1 && (waddr1 == 3)) ? wsrc2_1 : wsrc2_2),
		      .wvalid1((we1 && (waddr1 == 3)) ? wvalid1_1 : wvalid1_2),
		      .wvalid2((we1 && (waddr1 == 3)) ? wvalid2_1 : wvalid2_2),
		      .wimm((we1 && (waddr1 == 3)) ? wimm_1 : wimm_2),
		      .wrrftag((we1 && (waddr1 == 3)) ? wrrftag_1 : wrrftag_2),
		      .wdstval((we1 && (waddr1 == 3)) ? wdstval_1 : wdstval_2),
		      .walu_op((we1 && (waddr1 == 3)) ? walu_op_1 : walu_op_2),
		      .wspectag((we1 && (waddr1 == 3)) ? wspectag_1 : wspectag_2),
		      .wbhr((we1 && (waddr1 == 3)) ? wbhr_1 : wbhr_2),
		      .wpraddr((we1 && (waddr1 == 3)) ? wpraddr_1 : wpraddr_2),
		      .wprcond((we1 && (waddr1 == 3)) ? wprcond_1 : wprcond_2),
		      .wopcode((we1 && (waddr1 == 3)) ? wopcode_1 : wopcode_2),
		      .we((we1 && (waddr1 == 3)) || (we2 && (waddr2 == 3))),
		      .ex_src1(ex_src1_3),
		      .ex_src2(ex_src2_3),
		      .ready(ready_3),
		      .pc(pc_3),
		      .imm(imm_3),
		      .rrftag(rrftag_3),
		      .dstval(dstval_3),
		      .alu_op(alu_op_3),
		      .spectag(spectag_3),
		      .bhr(bhr_3),
		      .prcond(prcond_3),
		      .praddr(praddr_3),
		      .opcode(opcode_3),
		      .exrslt1(exrslt1),
		      .exdst1(exdst1),
		      .kill_spec1(kill_spec1),
		      .exrslt2(exrslt2),
		      .exdst2(exdst2),
		      .kill_spec2(kill_spec2),
		      .exrslt3(exrslt3),
		      .exdst3(exdst3),
		      .kill_spec3(kill_spec3),
		      .exrslt4(exrslt4),
		      .exdst4(exdst4),
		      .kill_spec4(kill_spec4),
		      .exrslt5(exrslt5),
		      .exdst5(exdst5),
		      .kill_spec5(kill_spec5)
		      );
   
   assign ex_src1 = (issueaddr == 0) ? ex_src1_0 :
		    (issueaddr == 1) ? ex_src1_1 :
		    (issueaddr == 2) ? ex_src1_2 : ex_src1_3;
   
   assign ex_src2 = (issueaddr == 0) ? ex_src2_0 :
		    (issueaddr == 1) ? ex_src2_1 :
		    (issueaddr == 2) ? ex_src2_2 : ex_src2_3;
   
   assign pc = (issueaddr == 0) ? pc_0 :
	       (issueaddr == 1) ? pc_1 :
	       (issueaddr == 2) ? pc_2 : pc_3;
   
   assign imm = (issueaddr == 0) ? imm_0 :
		(issueaddr == 1) ? imm_1 :
		(issueaddr == 2) ? imm_2 : imm_3;
   
   assign rrftag = (issueaddr == 0) ? rrftag_0 :
		   (issueaddr == 1) ? rrftag_1 :
		   (issueaddr == 2) ? rrftag_2 : rrftag_3;
   
   assign dstval = (issueaddr == 0) ? dstval_0 :
		   (issueaddr == 1) ? dstval_1 :
		   (issueaddr == 2) ? dstval_2 : dstval_3;

   assign alu_op = (issueaddr == 0) ? alu_op_0 :
		   (issueaddr == 1) ? alu_op_1 :
		   (issueaddr == 2) ? alu_op_2 : alu_op_3;

   assign spectag = (issueaddr == 0) ? spectag_0 :
		    (issueaddr == 1) ? spectag_1 :
		    (issueaddr == 2) ? spectag_2 : spectag_3;
   
   assign bhr = (issueaddr == 0) ? bhr_0 :
		(issueaddr == 1) ? bhr_1 :
		(issueaddr == 2) ? bhr_2 : bhr_3;
   
   assign prcond = (issueaddr == 0) ? prcond_0 :
		   (issueaddr == 1) ? prcond_1 :
		   (issueaddr == 2) ? prcond_2 : prcond_3;
   
   assign praddr = (issueaddr == 0) ? praddr_0 :
		   (issueaddr == 1) ? praddr_1 :
		   (issueaddr == 2) ? praddr_2 : praddr_3;
   
   assign opcode = (issueaddr == 0) ? opcode_0 :
		   (issueaddr == 1) ? opcode_1 :
		   (issueaddr == 2) ? opcode_2 : opcode_3;
   
   
endmodule // rs_branch
`default_nettype wire
`include "constants.vh"
`default_nettype none
module rs_ldst_ent
  (
   //Memory
   input wire 			 clk,
   input wire 			 reset,
   input wire 			 busy,
   input wire [`ADDR_LEN-1:0] 	 wpc,
   input wire [`DATA_LEN-1:0] 	 wsrc1,
   input wire [`DATA_LEN-1:0] 	 wsrc2,
   input wire 			 wvalid1,
   input wire 			 wvalid2,
   input wire [`DATA_LEN-1:0] 	 wimm,
   input wire [`RRF_SEL-1:0] 	 wrrftag,
   input wire 			 wdstval,
   input wire [`SPECTAG_LEN-1:0] 	 wspectag,
   input wire 			 we,
   output wire [`DATA_LEN-1:0] 	 ex_src1,
   output wire [`DATA_LEN-1:0] 	 ex_src2,
   output wire 			 ready,
   output reg [`ADDR_LEN-1:0] 	 pc,
   output reg [`DATA_LEN-1:0] 	 imm,
   output reg [`RRF_SEL-1:0] 	 rrftag,
   output reg 			 dstval,
   output reg [`SPECTAG_LEN-1:0] spectag,
   //EXRSLT
   input wire [`DATA_LEN-1:0] 	 exrslt1,
   input wire [`RRF_SEL-1:0] 	 exdst1,
   input wire 			 kill_spec1,
   input wire [`DATA_LEN-1:0] 	 exrslt2,
   input wire [`RRF_SEL-1:0] 	 exdst2,
   input wire 			 kill_spec2,
   input wire [`DATA_LEN-1:0] 	 exrslt3,
   input wire [`RRF_SEL-1:0] 	 exdst3,
   input wire 			 kill_spec3,
   input wire [`DATA_LEN-1:0] 	 exrslt4,
   input wire [`RRF_SEL-1:0] 	 exdst4,
   input wire 			 kill_spec4,
   input wire [`DATA_LEN-1:0] 	 exrslt5,
   input wire [`RRF_SEL-1:0] 	 exdst5,
   input wire 			 kill_spec5
   );

   reg [`DATA_LEN-1:0] 		 src1;
   reg [`DATA_LEN-1:0] 		 src2;
   reg 				 valid1;
   reg 				 valid2;

   wire [`DATA_LEN-1:0] 	 nextsrc1;
   wire [`DATA_LEN-1:0] 	 nextsrc2;   
   wire 			 nextvalid1;
   wire 			 nextvalid2;
   
   assign ready = busy & valid1 & valid2;
   assign ex_src1 = ~valid1 & nextvalid1 ?
		    nextsrc1 : src1;
   assign ex_src2 = ~valid2 & nextvalid2 ?
		    nextsrc2 : src2;
   
   always @ (posedge clk) begin
      if (reset) begin
	 pc <= 0;
	 imm <= 0;
	 rrftag <= 0;
	 dstval <= 0;
	 spectag <= 0;

	 src1 <= 0;
	 src2 <= 0;
	 valid1 <= 0;
	 valid2 <= 0;
      end else if (we) begin
	 pc <= wpc;
	 imm <= wimm;
	 rrftag <= wrrftag;
	 dstval <= wdstval;
	 spectag <= wspectag;

	 src1 <= wsrc1;
	 src2 <= wsrc2;
	 valid1 <= wvalid1;
	 valid2 <= wvalid2;
      end else begin // if (we)
	 src1 <= nextsrc1;
	 src2 <= nextsrc2;
	 valid1 <= nextvalid1;
	 valid2 <= nextvalid2;
      end
   end
   
   src_manager srcmng1(
		       .opr(src1),
		       .opr_rdy(valid1),
		       .exrslt1(exrslt1),
		       .exdst1(exdst1),
		       .kill_spec1(kill_spec1),
		       .exrslt2(exrslt2),
		       .exdst2(exdst2),
		       .kill_spec2(kill_spec2),
		       .exrslt3(exrslt3),
		       .exdst3(exdst3),
		       .kill_spec3(kill_spec3),
		       .exrslt4(exrslt4),
		       .exdst4(exdst4),
		       .kill_spec4(kill_spec4),
		       .exrslt5(exrslt5),
		       .exdst5(exdst5),
		       .kill_spec5(kill_spec5),
		       .src(nextsrc1),
		       .resolved(nextvalid1)
		       );

   src_manager srcmng2(
		       .opr(src2),
		       .opr_rdy(valid2),
		       .exrslt1(exrslt1),
		       .exdst1(exdst1),
		       .kill_spec1(kill_spec1),
		       .exrslt2(exrslt2),
		       .exdst2(exdst2),
		       .kill_spec2(kill_spec2),
		       .exrslt3(exrslt3),
		       .exdst3(exdst3),
		       .kill_spec3(kill_spec3),
		       .exrslt4(exrslt4),
		       .exdst4(exdst4),
		       .kill_spec4(kill_spec4),
		       .exrslt5(exrslt5),
		       .exdst5(exdst5),
		       .kill_spec5(kill_spec5),
		       .src(nextsrc2),
		       .resolved(nextvalid2)
		       );
   
endmodule // rs_ldst


module rs_ldst
  (
   //System
   input wire 			   clk,
   input wire 			   reset,
   output reg [`LDST_ENT_NUM-1:0]  busyvec,
   input wire 			   prmiss,
   input wire 			   prsuccess,
   input wire [`SPECTAG_LEN-1:0] 	   prtag,
   input wire [`SPECTAG_LEN-1:0] 	   specfixtag,
   output wire [`LDST_ENT_NUM-1:0] prbusyvec_next,
   //WriteSignal
   input wire 			   clearbusy, //Issue 
   input wire [`LDST_ENT_SEL-1:0] 	   issueaddr, //= raddr, clsbsyadr
   input wire 			   we1, //alloc1
   input wire 			   we2, //alloc2
   input wire [`LDST_ENT_SEL-1:0] 	   waddr1, //allocent1
   input wire [`LDST_ENT_SEL-1:0] 	   waddr2, //allocent2
   //WriteSignal1
   input wire [`ADDR_LEN-1:0] 	   wpc_1,
   input wire [`DATA_LEN-1:0] 	   wsrc1_1,
   input wire [`DATA_LEN-1:0] 	   wsrc2_1,
   input wire 			   wvalid1_1,
   input wire 			   wvalid2_1,
   input wire [`DATA_LEN-1:0] 	   wimm_1,
   input wire [`RRF_SEL-1:0] 	   wrrftag_1,
   input wire 			   wdstval_1,
   input wire [`SPECTAG_LEN-1:0] 	   wspectag_1,
   input wire 			   wspecbit_1,
   //WriteSignal2
   input wire [`ADDR_LEN-1:0] 	   wpc_2,
   input wire [`DATA_LEN-1:0] 	   wsrc1_2,
   input wire [`DATA_LEN-1:0] 	   wsrc2_2,
   input wire 			   wvalid1_2,
   input wire 			   wvalid2_2,
   input wire [`DATA_LEN-1:0] 	   wimm_2,
   input wire [`RRF_SEL-1:0] 	   wrrftag_2,
   input wire 			   wdstval_2,
   input wire [`SPECTAG_LEN-1:0] 	   wspectag_2,
   input wire 			   wspecbit_2,

   //ReadSignal
   output wire [`DATA_LEN-1:0] 	   ex_src1,
   output wire [`DATA_LEN-1:0] 	   ex_src2,
   output wire [`LDST_ENT_NUM-1:0] ready,
   output wire [`ADDR_LEN-1:0] 	   pc,
   output wire [`DATA_LEN-1:0] 	   imm,
   output wire [`RRF_SEL-1:0] 	   rrftag,
   output wire 			   dstval,
   output wire [`SPECTAG_LEN-1:0]  spectag,
   output wire 			   specbit,
  
   //EXRSLT
   input wire [`DATA_LEN-1:0] 	   exrslt1,
   input wire [`RRF_SEL-1:0] 	   exdst1,
   input wire 			   kill_spec1,
   input wire [`DATA_LEN-1:0] 	   exrslt2,
   input wire [`RRF_SEL-1:0] 	   exdst2,
   input wire 			   kill_spec2,
   input wire [`DATA_LEN-1:0] 	   exrslt3,
   input wire [`RRF_SEL-1:0] 	   exdst3,
   input wire 			   kill_spec3,
   input wire [`DATA_LEN-1:0] 	   exrslt4,
   input wire [`RRF_SEL-1:0] 	   exdst4,
   input wire 			   kill_spec4,
   input wire [`DATA_LEN-1:0] 	   exrslt5,
   input wire [`RRF_SEL-1:0] 	   exdst5,
   input wire 			   kill_spec5
   );

   //_0
   wire [`DATA_LEN-1:0] 	      ex_src1_0;
   wire [`DATA_LEN-1:0] 	      ex_src2_0;
   wire 			      ready_0;
   wire [`ADDR_LEN-1:0] 	      pc_0;
   wire [`DATA_LEN-1:0] 	      imm_0;
   wire [`RRF_SEL-1:0] 		      rrftag_0;
   wire 			      dstval_0;
   wire [`SPECTAG_LEN-1:0] 	      spectag_0;
   //_1
   wire [`DATA_LEN-1:0] 	      ex_src1_1;
   wire [`DATA_LEN-1:0] 	      ex_src2_1;
   wire 			      ready_1;
   wire [`ADDR_LEN-1:0] 	      pc_1;
   wire [`DATA_LEN-1:0] 	      imm_1;
   wire [`RRF_SEL-1:0] 		      rrftag_1;
   wire 			      dstval_1;
   wire [`SPECTAG_LEN-1:0] 	      spectag_1;
   //_2
   wire [`DATA_LEN-1:0] 	      ex_src1_2;
   wire [`DATA_LEN-1:0] 	      ex_src2_2;
   wire 			      ready_2;
   wire [`ADDR_LEN-1:0] 	      pc_2;
   wire [`DATA_LEN-1:0] 	      imm_2;
   wire [`RRF_SEL-1:0] 		      rrftag_2;
   wire 			      dstval_2;
   wire [`SPECTAG_LEN-1:0] 	      spectag_2;
   //_3
   wire [`DATA_LEN-1:0] 	      ex_src1_3;
   wire [`DATA_LEN-1:0] 	      ex_src2_3;
   wire 			      ready_3;
   wire [`ADDR_LEN-1:0] 	      pc_3;
   wire [`DATA_LEN-1:0] 	      imm_3;
   wire [`RRF_SEL-1:0] 		      rrftag_3;
   wire 			      dstval_3;
   wire [`SPECTAG_LEN-1:0] 	      spectag_3;
   
   reg [`LDST_ENT_NUM-1:0] 	   specbitvec;

   //busy invalidation
   wire [`LDST_ENT_NUM-1:0] 	   inv_vector =
				   {(spectag_3 & specfixtag) == 0 ? 1'b1 : 1'b0,
				    (spectag_2 & specfixtag) == 0 ? 1'b1 : 1'b0,
				    (spectag_1 & specfixtag) == 0 ? 1'b1 : 1'b0,
				    (spectag_0 & specfixtag) == 0 ? 1'b1 : 1'b0};

   wire [`LDST_ENT_NUM-1:0] 	   inv_vector_spec =
				   {(spectag_3 == prtag) ? 1'b0 : 1'b1,
				    (spectag_2 == prtag) ? 1'b0 : 1'b1,
				    (spectag_1 == prtag) ? 1'b0 : 1'b1,
				    (spectag_0 == prtag) ? 1'b0 : 1'b1};

   wire [`LDST_ENT_NUM-1:0] 	   specbitvec_next =
				   (inv_vector_spec & specbitvec);
   /*| 
				   (we1 & wspecbit_1 ? (`LDST_ENT_SEL'b1 << waddr1) : 0) |
				   (we2 & wspecbit_2 ? (`LDST_ENT_SEL'b1 << waddr2) : 0);
    */
   assign specbit = prsuccess ? 
		    specbitvec_next[issueaddr] : specbitvec[issueaddr];
   
   assign ready = {ready_3, ready_2, ready_1, ready_0};
   assign prbusyvec_next = inv_vector & busyvec;
   
   always @ (posedge clk) begin
      if (reset) begin
	 busyvec <= 0;
	 specbitvec <= 0;
      end else begin
	 if (prmiss) begin
	    busyvec <= prbusyvec_next;
	    specbitvec <= 0;
	 end else if (prsuccess) begin
	    specbitvec <= specbitvec_next;
	    /*
	    if (we1) begin
	       busyvec[waddr1] <= 1'b1;
	    end
	    if (we2) begin
	       busyvec[waddr2] <= 1'b1;
	    end
	     */
	    if (clearbusy) begin
	       busyvec[issueaddr] <= 1'b0;
	    end
	 end else begin
	    if (we1) begin
	       busyvec[waddr1] <= 1'b1;
	       specbitvec[waddr1] <= wspecbit_1;
	    end
	    if (we2) begin
	       busyvec[waddr2] <= 1'b1;
	       specbitvec[waddr2] <= wspecbit_2;
	    end
	    if (clearbusy) begin
	       busyvec[issueaddr] <= 1'b0;
	    end
	 end
      end
   end

   rs_ldst_ent ent0(
		    .clk(clk),
		    .reset(reset),
		    .busy(busyvec[0]),
		    .wpc((we1 && (waddr1 == 0)) ? wpc_1 : wpc_2),
		    .wsrc1((we1 && (waddr1 == 0)) ? wsrc1_1 : wsrc1_2),
		    .wsrc2((we1 && (waddr1 == 0)) ? wsrc2_1 : wsrc2_2),
		    .wvalid1((we1 && (waddr1 == 0)) ? wvalid1_1 : wvalid1_2),
		    .wvalid2((we1 && (waddr1 == 0)) ? wvalid2_1 : wvalid2_2),
		    .wimm((we1 && (waddr1 == 0)) ? wimm_1 : wimm_2),
		    .wrrftag((we1 && (waddr1 == 0)) ? wrrftag_1 : wrrftag_2),
		    .wdstval((we1 && (waddr1 == 0)) ? wdstval_1 : wdstval_2),
		    .wspectag((we1 && (waddr1 == 0)) ? wspectag_1 : wspectag_2),
		    .we((we1 && (waddr1 == 0)) || (we2 && (waddr2 == 0))),
		    .ex_src1(ex_src1_0),
		    .ex_src2(ex_src2_0),
		    .ready(ready_0),
		    .pc(pc_0),
		    .imm(imm_0),
		    .rrftag(rrftag_0),
		    .dstval(dstval_0),
		    .spectag(spectag_0),
		    .exrslt1(exrslt1),
		    .exdst1(exdst1),
		    .kill_spec1(kill_spec1),
		    .exrslt2(exrslt2),
		    .exdst2(exdst2),
		    .kill_spec2(kill_spec2),
		    .exrslt3(exrslt3),
		    .exdst3(exdst3),
		    .kill_spec3(kill_spec3),
		    .exrslt4(exrslt4),
		    .exdst4(exdst4),
		    .kill_spec4(kill_spec4),
		    .exrslt5(exrslt5),
		    .exdst5(exdst5),
		    .kill_spec5(kill_spec5)
		    );

   rs_ldst_ent ent1(
		    .clk(clk),
		    .reset(reset),		    
		    .busy(busyvec[1]),
		    .wpc((we1 && (waddr1 == 1)) ? wpc_1 : wpc_2),
		    .wsrc1((we1 && (waddr1 == 1)) ? wsrc1_1 : wsrc1_2),
		    .wsrc2((we1 && (waddr1 == 1)) ? wsrc2_1 : wsrc2_2),
		    .wvalid1((we1 && (waddr1 == 1)) ? wvalid1_1 : wvalid1_2),
		    .wvalid2((we1 && (waddr1 == 1)) ? wvalid2_1 : wvalid2_2),
		    .wimm((we1 && (waddr1 == 1)) ? wimm_1 : wimm_2),
		    .wrrftag((we1 && (waddr1 == 1)) ? wrrftag_1 : wrrftag_2),
		    .wdstval((we1 && (waddr1 == 1)) ? wdstval_1 : wdstval_2),
		    .wspectag((we1 && (waddr1 == 1)) ? wspectag_1 : wspectag_2),
		    .we((we1 && (waddr1 == 1)) || (we2 && (waddr2 == 1))),
		    .ex_src1(ex_src1_1),
		    .ex_src2(ex_src2_1),
		    .ready(ready_1),
		    .pc(pc_1),
		    .imm(imm_1),
		    .rrftag(rrftag_1),
		    .dstval(dstval_1),
		    .spectag(spectag_1),
		    .exrslt1(exrslt1),
		    .exdst1(exdst1),
		    .kill_spec1(kill_spec1),
		    .exrslt2(exrslt2),
		    .exdst2(exdst2),
		    .kill_spec2(kill_spec2),
		    .exrslt3(exrslt3),
		    .exdst3(exdst3),
		    .kill_spec3(kill_spec3),
		    .exrslt4(exrslt4),
		    .exdst4(exdst4),
		    .kill_spec4(kill_spec4),
		    .exrslt5(exrslt5),
		    .exdst5(exdst5),
		    .kill_spec5(kill_spec5)
		    );

   rs_ldst_ent ent2(
		    .clk(clk),
		    .reset(reset),		    
		    .busy(busyvec[2]),
		    .wpc((we1 && (waddr1 == 2)) ? wpc_1 : wpc_2),
		    .wsrc1((we1 && (waddr1 == 2)) ? wsrc1_1 : wsrc1_2),
		    .wsrc2((we1 && (waddr1 == 2)) ? wsrc2_1 : wsrc2_2),
		    .wvalid1((we1 && (waddr1 == 2)) ? wvalid1_1 : wvalid1_2),
		    .wvalid2((we1 && (waddr1 == 2)) ? wvalid2_1 : wvalid2_2),
		    .wimm((we1 && (waddr1 == 2)) ? wimm_1 : wimm_2),
		    .wrrftag((we1 && (waddr1 == 2)) ? wrrftag_1 : wrrftag_2),
		    .wdstval((we1 && (waddr1 == 2)) ? wdstval_1 : wdstval_2),
		    .wspectag((we1 && (waddr1 == 2)) ? wspectag_1 : wspectag_2),
		    .we((we1 && (waddr1 == 2)) || (we2 && (waddr2 == 2))),
		    .ex_src1(ex_src1_2),
		    .ex_src2(ex_src2_2),
		    .ready(ready_2),
		    .pc(pc_2),
		    .imm(imm_2),
		    .rrftag(rrftag_2),
		    .dstval(dstval_2),
		    .spectag(spectag_2),
		    .exrslt1(exrslt1),
		    .exdst1(exdst1),
		    .kill_spec1(kill_spec1),
		    .exrslt2(exrslt2),
		    .exdst2(exdst2),
		    .kill_spec2(kill_spec2),
		    .exrslt3(exrslt3),
		    .exdst3(exdst3),
		    .kill_spec3(kill_spec3),
		    .exrslt4(exrslt4),
		    .exdst4(exdst4),
		    .kill_spec4(kill_spec4),
		    .exrslt5(exrslt5),
		    .exdst5(exdst5),
		    .kill_spec5(kill_spec5)
		    );

   rs_ldst_ent ent3(
		    .clk(clk),
		    .reset(reset),		    
		    .busy(busyvec[3]),
		    .wpc((we1 && (waddr1 == 3)) ? wpc_1 : wpc_2),
		    .wsrc1((we1 && (waddr1 == 3)) ? wsrc1_1 : wsrc1_2),
		    .wsrc2((we1 && (waddr1 == 3)) ? wsrc2_1 : wsrc2_2),
		    .wvalid1((we1 && (waddr1 == 3)) ? wvalid1_1 : wvalid1_2),
		    .wvalid2((we1 && (waddr1 == 3)) ? wvalid2_1 : wvalid2_2),
		    .wimm((we1 && (waddr1 == 3)) ? wimm_1 : wimm_2),
		    .wrrftag((we1 && (waddr1 == 3)) ? wrrftag_1 : wrrftag_2),
		    .wdstval((we1 && (waddr1 == 3)) ? wdstval_1 : wdstval_2),
		    .wspectag((we1 && (waddr1 == 3)) ? wspectag_1 : wspectag_2),
		    .we((we1 && (waddr1 == 3)) || (we2 && (waddr2 == 3))),
		    .ex_src1(ex_src1_3),
		    .ex_src2(ex_src2_3),
		    .ready(ready_3),
		    .pc(pc_3),
		    .imm(imm_3),
		    .rrftag(rrftag_3),
		    .dstval(dstval_3),
		    .spectag(spectag_3),
		    .exrslt1(exrslt1),
		    .exdst1(exdst1),
		    .kill_spec1(kill_spec1),
		    .exrslt2(exrslt2),
		    .exdst2(exdst2),
		    .kill_spec2(kill_spec2),
		    .exrslt3(exrslt3),
		    .exdst3(exdst3),
		    .kill_spec3(kill_spec3),
		    .exrslt4(exrslt4),
		    .exdst4(exdst4),
		    .kill_spec4(kill_spec4),
		    .exrslt5(exrslt5),
		    .exdst5(exdst5),
		    .kill_spec5(kill_spec5)
		    );

   
   assign ex_src1 = (issueaddr == 0) ? ex_src1_0 :
		    (issueaddr == 1) ? ex_src1_1 :
		    (issueaddr == 2) ? ex_src1_2 : ex_src1_3;

   assign ex_src2 = (issueaddr == 0) ? ex_src2_0 :
		    (issueaddr == 1) ? ex_src2_1 :
		    (issueaddr == 2) ? ex_src2_2 : ex_src2_3;

   assign pc = (issueaddr == 0) ? pc_0 :
	       (issueaddr == 1) ? pc_1 :
	       (issueaddr == 2) ? pc_2 : pc_3;

   assign imm = (issueaddr == 0) ? imm_0 :
		(issueaddr == 1) ? imm_1 :
		(issueaddr == 2) ? imm_2 : imm_3;

   assign rrftag = (issueaddr == 0) ? rrftag_0 :
		   (issueaddr == 1) ? rrftag_1 :
		   (issueaddr == 2) ? rrftag_2 : rrftag_3;

   assign dstval = (issueaddr == 0) ? dstval_0 :
		   (issueaddr == 1) ? dstval_1 :
		   (issueaddr == 2) ? dstval_2 : dstval_3;

   assign spectag = (issueaddr == 0) ? spectag_0 :
		    (issueaddr == 1) ? spectag_1 :
		    (issueaddr == 2) ? spectag_2 : spectag_3;
   
   
endmodule // rs_ldst
`default_nettype wire
`include "constants.vh"
`include "alu_ops.vh"
`default_nettype none
module rs_mul_ent
  (
   //Memory
   input wire 			 clk,
   input wire 			 reset,
   input wire 			 busy,
   input wire [`DATA_LEN-1:0] 	 wsrc1,
   input wire [`DATA_LEN-1:0] 	 wsrc2,
   input wire 			 wvalid1,
   input wire 			 wvalid2,
   input wire [`RRF_SEL-1:0] 	 wrrftag,
   input wire 			 wdstval,
   input wire [`SPECTAG_LEN-1:0] 	 wspectag,
   input wire 			 wsrc1_signed,
   input wire 			 wsrc2_signed,
   input wire 			 wsel_lohi,
   input wire 			 we,
   output wire [`DATA_LEN-1:0] 	 ex_src1,
   output wire [`DATA_LEN-1:0] 	 ex_src2,
   output wire 			 ready,
   output reg [`RRF_SEL-1:0] 	 rrftag,
   output reg 			 dstval,
   output reg [`SPECTAG_LEN-1:0] spectag,
   output reg 			 src1_signed,
   output reg 			 src2_signed,
   output reg 			 sel_lohi,
   //EXRSLT
   input wire [`DATA_LEN-1:0] 	 exrslt1,
   input wire [`RRF_SEL-1:0] 	 exdst1,
   input wire 			 kill_spec1,
   input wire [`DATA_LEN-1:0] 	 exrslt2,
   input wire [`RRF_SEL-1:0] 	 exdst2,
   input wire 			 kill_spec2,
   input wire [`DATA_LEN-1:0] 	 exrslt3,
   input wire [`RRF_SEL-1:0] 	 exdst3,
   input wire 			 kill_spec3,
   input wire [`DATA_LEN-1:0] 	 exrslt4,
   input wire [`RRF_SEL-1:0] 	 exdst4,
   input wire 			 kill_spec4,
   input wire [`DATA_LEN-1:0] 	 exrslt5,
   input wire [`RRF_SEL-1:0] 	 exdst5,
   input wire 			 kill_spec5
   );

   reg [`DATA_LEN-1:0] 		 src1;
   reg [`DATA_LEN-1:0] 		 src2;
   reg 				 valid1;
   reg 				 valid2;

   wire [`DATA_LEN-1:0] 	 nextsrc1;
   wire [`DATA_LEN-1:0] 	 nextsrc2;   
   wire 			 nextvalid1;
   wire 			 nextvalid2;
   
   assign ready = busy & valid1 & valid2;
   assign ex_src1 = ~valid1 & nextvalid1 ?
		    nextsrc1 : src1;
   assign ex_src2 = ~valid2 & nextvalid2 ?
		    nextsrc2 : src2;
   
   always @ (posedge clk) begin
      if (reset) begin
	 rrftag <= 0;
	 dstval <= 0;
	 spectag <= 0;
	 src1_signed <= 0;
	 src2_signed <= 0;
	 sel_lohi <= 0;

	 src1 <= 0;
	 src2 <= 0;
	 valid1 <= 0;
	 valid2 <= 0;
      end else if (we) begin
	 rrftag <= wrrftag;
	 dstval <= wdstval;
	 spectag <= wspectag;
	 src1_signed <= wsrc1_signed;
	 src2_signed <= wsrc2_signed;
	 sel_lohi <= wsel_lohi;

	 src1 <= wsrc1;
	 src2 <= wsrc2;
	 valid1 <= wvalid1;
	 valid2 <= wvalid2;
      end else begin // if (we)
	 src1 <= nextsrc1;
	 src2 <= nextsrc2;
	 valid1 <= nextvalid1;
	 valid2 <= nextvalid2;
      end
   end
   
   src_manager srcmng1(
		       .opr(src1),
		       .opr_rdy(valid1),
		       .exrslt1(exrslt1),
		       .exdst1(exdst1),
		       .kill_spec1(kill_spec1),
		       .exrslt2(exrslt2),
		       .exdst2(exdst2),
		       .kill_spec2(kill_spec2),
		       .exrslt3(exrslt3),
		       .exdst3(exdst3),
		       .kill_spec3(kill_spec3),
		       .exrslt4(exrslt4),
		       .exdst4(exdst4),
		       .kill_spec4(kill_spec4),
		       .exrslt5(exrslt5),
		       .exdst5(exdst5),
		       .kill_spec5(kill_spec5),
		       .src(nextsrc1),
		       .resolved(nextvalid1)
		       );

   src_manager srcmng2(
		       .opr(src2),
		       .opr_rdy(valid2),
		       .exrslt1(exrslt1),
		       .exdst1(exdst1),
		       .kill_spec1(kill_spec1),
		       .exrslt2(exrslt2),
		       .exdst2(exdst2),
		       .kill_spec2(kill_spec2),
		       .exrslt3(exrslt3),
		       .exdst3(exdst3),
		       .kill_spec3(kill_spec3),
		       .exrslt4(exrslt4),
		       .exdst4(exdst4),
		       .kill_spec4(kill_spec4),
		       .exrslt5(exrslt5),
		       .exdst5(exdst5),
		       .kill_spec5(kill_spec5),
		       .src(nextsrc2),
		       .resolved(nextvalid2)
		       );
   
endmodule // rs_mul


module rs_mul
  (
   //System
   input wire 			  clk,
   input wire 			  reset,
   output reg [`MUL_ENT_NUM-1:0]  busyvec,
   input wire 			  prmiss,
   input wire 			  prsuccess,
   input wire [`SPECTAG_LEN-1:0] 	  prtag,
   input wire [`SPECTAG_LEN-1:0] 	  specfixtag,
   //WriteSignal
   input wire 			  clearbusy, //Issue 
   input wire [`MUL_ENT_SEL-1:0] 	  issueaddr, //= raddr, clsbsyadr
   input wire 			  we1, //alloc1
   input wire 			  we2, //alloc2
   input wire [`MUL_ENT_SEL-1:0] 	  waddr1, //allocent1
   input wire [`MUL_ENT_SEL-1:0] 	  waddr2, //allocent2
   //WriteSignal1
   input wire [`DATA_LEN-1:0] 	  wsrc1_1,
   input wire [`DATA_LEN-1:0] 	  wsrc2_1,
   input wire 			  wvalid1_1,
   input wire 			  wvalid2_1,
   input wire [`RRF_SEL-1:0] 	  wrrftag_1,
   input wire 			  wdstval_1,
   input wire [`SPECTAG_LEN-1:0] 	  wspectag_1,
   input wire 			  wspecbit_1,
   input wire 			  wsrc1_signed_1,
   input wire 			  wsrc2_signed_1,
   input wire 			  wsel_lohi_1,

   //WriteSignal2
   input wire [`DATA_LEN-1:0] 	  wsrc1_2,
   input wire [`DATA_LEN-1:0] 	  wsrc2_2,
   input wire 			  wvalid1_2,
   input wire 			  wvalid2_2,
   input wire [`RRF_SEL-1:0] 	  wrrftag_2,
   input wire 			  wdstval_2,
   input wire [`SPECTAG_LEN-1:0] 	  wspectag_2,
   input wire 			  wspecbit_2,
   input wire 			  wsrc1_signed_2,
   input wire 			  wsrc2_signed_2,
   input wire 			  wsel_lohi_2,

   //ReadSignal
   output wire [`DATA_LEN-1:0] 	  ex_src1,
   output wire [`DATA_LEN-1:0] 	  ex_src2,
   output wire [`MUL_ENT_NUM-1:0] ready,
   output wire [`RRF_SEL-1:0] 	  rrftag,
   output wire 			  dstval,
   output wire [`SPECTAG_LEN-1:0] spectag,
   output wire 			  specbit,
   output wire 			  src1_signed,
   output wire 			  src2_signed,
   output wire 			  sel_lohi,

   //EXRSLT
   input wire [`DATA_LEN-1:0] 	  exrslt1,
   input wire [`RRF_SEL-1:0] 	  exdst1,
   input wire 			  kill_spec1,
   input wire [`DATA_LEN-1:0] 	  exrslt2,
   input wire [`RRF_SEL-1:0] 	  exdst2,
   input wire 			  kill_spec2,
   input wire [`DATA_LEN-1:0] 	  exrslt3,
   input wire [`RRF_SEL-1:0] 	  exdst3,
   input wire 			  kill_spec3,
   input wire [`DATA_LEN-1:0] 	  exrslt4,
   input wire [`RRF_SEL-1:0] 	  exdst4,
   input wire 			  kill_spec4,
   input wire [`DATA_LEN-1:0] 	  exrslt5,
   input wire [`RRF_SEL-1:0] 	  exdst5,
   input wire 			  kill_spec5
   );

   //_0
   wire [`DATA_LEN-1:0] 	      ex_src1_0;
   wire [`DATA_LEN-1:0] 	      ex_src2_0;
   wire 			      ready_0;
   wire [`RRF_SEL-1:0] 		      rrftag_0;
   wire 			      dstval_0;
   wire [`SPECTAG_LEN-1:0] 	      spectag_0;
   wire 			      src1_signed_0;
   wire 			      src2_signed_0;
   wire 			      sel_lohi_0;
   
   //_1
   wire [`DATA_LEN-1:0] 	      ex_src1_1;
   wire [`DATA_LEN-1:0] 	      ex_src2_1;
   wire 			      ready_1;
   wire [`RRF_SEL-1:0] 		      rrftag_1;
   wire 			      dstval_1;
   wire [`SPECTAG_LEN-1:0] 	      spectag_1;
   wire 			      src1_signed_1;
   wire 			      src2_signed_1;
   wire 			      sel_lohi_1;

   reg [`MUL_ENT_NUM-1:0] 	  specbitvec;

   wire [`MUL_ENT_NUM-1:0] 	  inv_vector =
				  {(spectag_1 & specfixtag) == 0 ? 1'b1 : 1'b0,
				   (spectag_0 & specfixtag) == 0 ? 1'b1 : 1'b0};

   wire [`MUL_ENT_NUM-1:0] 	  inv_vector_spec =
				  {(spectag_1 == prtag) ? 1'b0 : 1'b1,
				   (spectag_0 == prtag) ? 1'b0 : 1'b1};

   wire [`MUL_ENT_NUM-1:0] 	  specbitvec_next =
				  (inv_vector_spec & specbitvec);
   /* |
				  (we1 & wspecbit_1 ? (`MUL_ENT_SEL'b1 << waddr1) : 0) |
				  (we2 & wspecbit_2 ? (`MUL_ENT_SEL'b1 << waddr2) : 0);
    */
   assign specbit = prsuccess ? 
		    specbitvec_next[issueaddr] : specbitvec[issueaddr];

   assign ready = {ready_1, ready_0};
   
   always @ (posedge clk) begin
      if (reset) begin
	 busyvec <= 0;
	 specbitvec <= 0;
      end else begin
	 if (prmiss) begin
	    busyvec <= inv_vector & busyvec;
	    specbitvec <= 0;
	 end else if (prsuccess) begin
	    specbitvec <= specbitvec_next;
	    /*
	    if (we1) begin
	       busyvec[waddr1] <= 1'b1;
	    end
	    if (we2) begin
	       busyvec[waddr2] <= 1'b1;
	    end
	     */
	    if (clearbusy) begin
	       busyvec[issueaddr] <= 1'b0;
	    end
	 end else begin
	    if (we1) begin
	       busyvec[waddr1] <= 1'b1;
	       specbitvec[waddr1] <= wspecbit_1;
	    end
	    if (we2) begin
	       busyvec[waddr2] <= 1'b1;
	       specbitvec[waddr2] <= wspecbit_2;
	    end
	    if (clearbusy) begin
	       busyvec[issueaddr] <= 1'b0;
	    end
	 end
      end
   end

   rs_mul_ent ent0(
		   .clk(clk),
		   .reset(reset),		      		   
		   .busy(busyvec[0]),
		   .wsrc1((we1 && (waddr1 == 0)) ? wsrc1_1 : wsrc1_2),
		   .wsrc2((we1 && (waddr1 == 0)) ? wsrc2_1 : wsrc2_2),
		   .wvalid1((we1 && (waddr1 == 0)) ? wvalid1_1 : wvalid1_2),
		   .wvalid2((we1 && (waddr1 == 0)) ? wvalid2_1 : wvalid2_2),
		   .wrrftag((we1 && (waddr1 == 0)) ? wrrftag_1 : wrrftag_2),
		   .wdstval((we1 && (waddr1 == 0)) ? wdstval_1 : wdstval_2),
		   .wspectag((we1 && (waddr1 == 0)) ? wspectag_1 : wspectag_2),
		   .wsrc1_signed((we1 && (waddr1 == 0)) ? wsrc1_signed_1 : wsrc1_signed_2),
		   .wsrc2_signed((we1 && (waddr1 == 0)) ? wsrc2_signed_1 : wsrc2_signed_2),
		   .wsel_lohi((we1 && (waddr1 == 0)) ? wsel_lohi_1 : wsel_lohi_2),
		   .we((we1 && (waddr1 == 0)) || (we2 && (waddr2 == 0))),
		   .ex_src1(ex_src1_0),
		   .ex_src2(ex_src2_0),
		   .ready(ready_0),
		   .rrftag(rrftag_0),
		   .dstval(dstval_0),
		   .spectag(spectag_0),
		   .src1_signed(src1_signed_0),
		   .src2_signed(src2_signed_0),
		   .sel_lohi(sel_lohi_0),
		   .exrslt1(exrslt1),
		   .exdst1(exdst1),
		   .kill_spec1(kill_spec1),
		   .exrslt2(exrslt2),
		   .exdst2(exdst2),
		   .kill_spec2(kill_spec2),
		   .exrslt3(exrslt3),
		   .exdst3(exdst3),
		   .kill_spec3(kill_spec3),
		   .exrslt4(exrslt4),
		   .exdst4(exdst4),
		   .kill_spec4(kill_spec4),
		   .exrslt5(exrslt5),
		   .exdst5(exdst5),
		   .kill_spec5(kill_spec5)
		   );

   rs_mul_ent ent1(
		   .clk(clk),
		   .reset(reset),		   
		   .busy(busyvec[1]),
		   .wsrc1((we1 && (waddr1 == 1)) ? wsrc1_1 : wsrc1_2),
		   .wsrc2((we1 && (waddr1 == 1)) ? wsrc2_1 : wsrc2_2),
		   .wvalid1((we1 && (waddr1 == 1)) ? wvalid1_1 : wvalid1_2),
		   .wvalid2((we1 && (waddr1 == 1)) ? wvalid2_1 : wvalid2_2),
		   .wrrftag((we1 && (waddr1 == 1)) ? wrrftag_1 : wrrftag_2),
		   .wdstval((we1 && (waddr1 == 1)) ? wdstval_1 : wdstval_2),
		   .wspectag((we1 && (waddr1 == 1)) ? wspectag_1 : wspectag_2),
		   .wsrc1_signed((we1 && (waddr1 == 1)) ? wsrc1_signed_1 : wsrc1_signed_2),
		   .wsrc2_signed((we1 && (waddr1 == 1)) ? wsrc2_signed_1 : wsrc2_signed_2),
		   .wsel_lohi((we1 && (waddr1 == 1)) ? wsel_lohi_1 : wsel_lohi_2),
		   .we((we1 && (waddr1 == 1)) || (we2 && (waddr2 == 1))),
		   .ex_src1(ex_src1_1),
		   .ex_src2(ex_src2_1),
		   .ready(ready_1),
		   .rrftag(rrftag_1),
		   .dstval(dstval_1),
		   .spectag(spectag_1),
		   .src1_signed(src1_signed_1),
		   .src2_signed(src2_signed_1),
		   .sel_lohi(sel_lohi_1),
		   .exrslt1(exrslt1),
		   .exdst1(exdst1),
		   .kill_spec1(kill_spec1),
		   .exrslt2(exrslt2),
		   .exdst2(exdst2),
		   .kill_spec2(kill_spec2),
		   .exrslt3(exrslt3),
		   .exdst3(exdst3),
		   .kill_spec3(kill_spec3),
		   .exrslt4(exrslt4),
		   .exdst4(exdst4),
		   .kill_spec4(kill_spec4),
		   .exrslt5(exrslt5),
		   .exdst5(exdst5),
		   .kill_spec5(kill_spec5)
		   );
   
   assign ex_src1 = (issueaddr == 0) ? ex_src1_0 : ex_src1_1;
   
   assign ex_src2 = (issueaddr == 0) ? ex_src2_0 : ex_src2_1;

   assign rrftag = (issueaddr == 0) ? rrftag_0 : rrftag_1;
   
   assign dstval = (issueaddr == 0) ? dstval_0 : dstval_1;

   assign spectag = (issueaddr == 0) ? spectag_0 : spectag_1;

   assign src1_signed = (issueaddr == 0) ? src1_signed_0 : src1_signed_1;

   assign src2_signed = (issueaddr == 0) ? src2_signed_0 : src2_signed_1;

   assign sel_lohi = (issueaddr == 0) ? sel_lohi_0 : sel_lohi_1;   
endmodule // rs_mul
`default_nettype wire
`include "constants.vh"
`default_nettype none
module rs_requestgenerator
  (
   input wire [`RS_ENT_SEL-1:0] rsent_1,
   input wire [`RS_ENT_SEL-1:0] rsent_2,
   output wire 			req1_alu,
   output wire 			req2_alu,
   output wire [1:0] 		req_alunum,
   output wire 			req1_branch,
   output wire 			req2_branch,
   output wire [1:0] 		req_branchnum,
   output wire 			req1_mul,
   output wire 			req2_mul,
   output wire [1:0] 		req_mulnum,
   output wire 			req1_ldst,
   output wire 			req2_ldst,
   output wire [1:0] 		req_ldstnum
   );

   assign req1_alu = (rsent_1 == `RS_ENT_ALU) ? 1'b1 : 1'b0;
   assign req2_alu = (rsent_2 == `RS_ENT_ALU) ? 1'b1 : 1'b0;
   assign req_alunum = {1'b0, req1_alu} + {1'b0, req2_alu};

   assign req1_branch = (rsent_1 == `RS_ENT_BRANCH) ? 1'b1 : 1'b0;
   assign req2_branch = (rsent_2 == `RS_ENT_BRANCH) ? 1'b1 : 1'b0;
   assign req_branchnum = {1'b0, req1_branch} + {1'b0, req2_branch};

   assign req1_mul = (rsent_1 == `RS_ENT_MUL) ? 1'b1 : 1'b0;
   assign req2_mul = (rsent_2 == `RS_ENT_MUL) ? 1'b1 : 1'b0;
   assign req_mulnum = {1'b0, req1_mul} + {1'b0, req2_mul};

   assign req1_ldst = (rsent_1 == `RS_ENT_LDST) ? 1'b1 : 1'b0;
   assign req2_ldst = (rsent_2 == `RS_ENT_LDST) ? 1'b1 : 1'b0;
   assign req_ldstnum = {1'b0, req1_ldst} + {1'b0, req2_ldst};
   
endmodule // rs_requestgenerator
`default_nettype wire

module search_begin #(
		      parameter ENTSEL = 2,
		      parameter ENTNUM = 4
		     )
  (
   input wire [ENTNUM-1:0] in,
   output reg [ENTSEL-1:0] out,
   output reg 		   en
   );

   integer 		   i;
   always @ (*) begin
      out = 0;
      en = 0;
      for (i = ENTNUM-1; i >= 0 ; i = i - 1) begin
	 if (in[i]) begin
	    out = i;
	    en = 1;
	 end
      end
   end
   
endmodule // search_from_top

module search_end #(
		    parameter ENTSEL = 2,
		    parameter ENTNUM = 4
		    )
   (
    input wire [ENTNUM-1:0] in,
    output reg [ENTSEL-1:0] out,
    output reg 		    en
   );

   integer 		   i;
   always @ (*) begin
      out = 0;
      en = 0;
      for (i = 0 ; i < ENTNUM ; i = i + 1) begin
	 if (in[i]) begin
	    out = i;
	    en = 1;
	 end
      end
   end

endmodule // search_from_bottom
`include "constants.vh"
`default_nettype none
module src_manager
  (
   input wire [`DATA_LEN-1:0]  opr,
   input wire 		       opr_rdy,
   input wire [`DATA_LEN-1:0]  exrslt1,
   input wire [`RRF_SEL-1:0]   exdst1,
   input wire 		       kill_spec1,
   input wire [`DATA_LEN-1:0]  exrslt2,
   input wire [`RRF_SEL-1:0]   exdst2,
   input wire 		       kill_spec2,
   input wire [`DATA_LEN-1:0]  exrslt3,
   input wire [`RRF_SEL-1:0]   exdst3,
   input wire 		       kill_spec3,
   input wire [`DATA_LEN-1:0]  exrslt4,
   input wire [`RRF_SEL-1:0]   exdst4,
   input wire 		       kill_spec4,
   input wire [`DATA_LEN-1:0]  exrslt5,
   input wire [`RRF_SEL-1:0]   exdst5,
   input wire 		       kill_spec5,
   output wire [`DATA_LEN-1:0] src,
   output wire 		       resolved
   );

   assign src = opr_rdy ? opr :
		~kill_spec1 & (exdst1 == opr) ? exrslt1 :
		~kill_spec2 & (exdst2 == opr) ? exrslt2 :
		~kill_spec3 & (exdst3 == opr) ? exrslt3 :
		~kill_spec4 & (exdst4 == opr) ? exrslt4 :
		~kill_spec5 & (exdst5 == opr) ? exrslt5 : opr;

   assign resolved = opr_rdy |
		     (~kill_spec1 & (exdst1 == opr)) |
		     (~kill_spec2 & (exdst2 == opr)) |
		     (~kill_spec3 & (exdst3 == opr)) |
		     (~kill_spec4 & (exdst4 == opr)) |
		     (~kill_spec5 & (exdst5 == opr));
   
endmodule // src_manager


`default_nettype wire
`include "constants.vh"
`default_nettype none
module sourceoperand_manager
  (
   input wire [`DATA_LEN-1:0]  arfdata,
   input wire 		       arf_busy,
   input wire 		       rrf_valid,
   input wire [`RRF_SEL-1:0]   rrftag,
   input wire [`DATA_LEN-1:0]  rrfdata,
   input wire [`RRF_SEL-1:0]   dst1_renamed,
   input wire 		       src_eq_dst1,
   input wire 		       src_eq_0,
   output wire [`DATA_LEN-1:0] src,
   output wire 		       rdy
   );

   assign src = src_eq_0 ? `DATA_LEN'b0 :
		src_eq_dst1 ? dst1_renamed :
		~arf_busy ? arfdata :
		rrf_valid ? rrfdata :
		rrftag;
   assign rdy = src_eq_0 | (~src_eq_dst1 & (~arf_busy | rrf_valid));

endmodule // sourceoperand_manager
`default_nettype wire
`include "rv32_opcodes.vh"
`include "constants.vh"
`default_nettype none
module src_a_mux(
                 input wire [`SRC_A_SEL_WIDTH-1:0] src_a_sel,
                 input wire [`ADDR_LEN-1:0] 	   pc,
                 input wire [`DATA_LEN-1:0] 	   rs1,
                 output reg [`DATA_LEN-1:0] 	   alu_src_a
                 );


   always @(*) begin
      case (src_a_sel)
        `SRC_A_RS1 : alu_src_a = rs1;
        `SRC_A_PC : alu_src_a = pc;
        default : alu_src_a = 0;
      endcase // case (src_a_sel)
   end

endmodule // src_a_mux


module src_b_mux(
                 input wire [`SRC_B_SEL_WIDTH-1:0] src_b_sel,
                 input wire [`DATA_LEN-1:0] 	   imm,
                 input wire [`DATA_LEN-1:0] 	   rs2,
                 output reg [`DATA_LEN-1:0] 	   alu_src_b
                 );


   always @(*) begin
      case (src_b_sel)
        `SRC_B_RS2 : alu_src_b = rs2;
        `SRC_B_IMM : alu_src_b = imm;
        `SRC_B_FOUR : alu_src_b = 4;
        default : alu_src_b = 0;
      endcase // case (src_b_sel)
   end

endmodule // src_b_mux
`default_nettype wire
`include "constants.vh"

module storebuf
  (
   input wire 			 clk,
   input wire 			 reset,
   input wire 			 prsuccess,
   input wire 			 prmiss,
   input wire [`SPECTAG_LEN-1:0] prtag,
   input wire [`SPECTAG_LEN-1:0] spectagfix,
   input wire 			 stfin,
   input wire 			 stspecbit,
   input wire [`SPECTAG_LEN-1:0] stspectag,
   input wire [`DATA_LEN-1:0] 	 stdata,
   input wire [`ADDR_LEN-1:0] 	 staddr,
   input wire 			 stcom,
   output wire 			 stretire, //dmem_we
   output wire [`DATA_LEN-1:0] 	 retdata,
   output wire [`ADDR_LEN-1:0] 	 retaddr,
   input wire 			 memoccupy_ld,
   output wire 			 sb_full,
   //ReadSigs
   input wire [`ADDR_LEN-1:0] 	 ldaddr,
   output wire [`DATA_LEN-1:0] 	 lddata,
   output wire 			 hit
   );

   reg [`STBUF_ENT_SEL-1:0] 	 finptr;
   reg [`STBUF_ENT_SEL-1:0] 	 comptr;
   reg [`STBUF_ENT_SEL-1:0] 	 retptr;
   
   reg [`SPECTAG_LEN-1:0] 	 spectag [0:`STBUF_ENT_NUM-1];
   reg [`STBUF_ENT_NUM-1:0] 	 completed;
   reg [`STBUF_ENT_NUM-1:0] 	 valid;
   reg [`STBUF_ENT_NUM-1:0] 	 specbit;
   reg [`DATA_LEN-1:0] 		 data [0:`STBUF_ENT_NUM-1];
   reg [`ADDR_LEN-1:0] 		 addr [0:`STBUF_ENT_NUM-1];

   //when prsuccess, specbit_next = specbit & specbitcls
   wire [`STBUF_ENT_NUM-1:0] 	 specbit_cls;
   wire [`STBUF_ENT_NUM-1:0] 	 valid_cls;
   wire 			 notfull_next;
   wire 			 notempty_next;
   wire [`STBUF_ENT_SEL-1:0] 	 nb1;
   wire [`STBUF_ENT_SEL-1:0] 	 ne1;
   wire [`STBUF_ENT_SEL-1:0] 	 nb0;
   wire [`STBUF_ENT_SEL-1:0] 	 finptr_next;
   //For CAM with Priority
   wire [`STBUF_ENT_NUM-1:0] 	 hitvec;
   wire [2*`STBUF_ENT_NUM-1:0] 	 hitvec_rot;
   wire [`STBUF_ENT_SEL-1:0] 	 ldent_rot;
   wire [`STBUF_ENT_SEL-1:0] 	 ldent;
   wire [`STBUF_ENT_SEL-1:0] 	 vecshamt;
   
   search_begin #(`STBUF_ENT_SEL, `STBUF_ENT_NUM) 
   snb1(
	.in(valid & valid_cls),
	.out(nb1),
	.en()
	);
   
   search_end #(`STBUF_ENT_SEL, `STBUF_ENT_NUM) 
   sne1(
	.in(valid & valid_cls),
	.out(ne1),
	.en(notempty_next)
	);

   search_begin #(`STBUF_ENT_SEL, `STBUF_ENT_NUM) 
   snb0(
	.in(~(valid & valid_cls)),
	.out(nb0),
	.en(notfull_next)
	);

   search_end #(`STBUF_ENT_SEL, `STBUF_ENT_NUM)
   findhitent(
	      .in(hitvec_rot[2*`STBUF_ENT_NUM-1:`STBUF_ENT_NUM]),
	      .out(ldent_rot),
	      .en(hit)
	      );
   
   assign retdata = data[retptr];
   assign retaddr = addr[retptr];
   assign lddata = data[ldent];
   assign stretire = valid[retptr] && completed[retptr] && ~memoccupy_ld &&
		     ~prmiss;
   assign sb_full = ((finptr == retptr) && (valid[finptr] == 1)) ? 1'b1 : 1'b0;
   assign finptr_next = (~notfull_next | ~notempty_next) ? finptr :
			(((nb1 == 0) && (ne1 == `STBUF_ENT_NUM-1)) ? nb0 : (ne1+1));
   assign vecshamt = (`STBUF_ENT_NUM - finptr);
   assign hitvec_rot = {hitvec, hitvec} << vecshamt;
   assign ldent = ldent_rot + finptr;
   
   generate
      genvar 			 i;
      for (i = 0 ; i < `STBUF_ENT_NUM ; i = i + 1) 
	begin: L1
	   assign specbit_cls[i] = (prtag == spectag[i]) ? 1'b0 : 1'b1;
	   assign valid_cls[i] = (specbit[i] && ((spectagfix & spectag[i]) != 0)) ? 
				 1'b0 : 1'b1;
	   assign hitvec[i] = (valid[i] && (addr[i] == ldaddr)) ? 1'b1 : 1'b0;
	end
   endgenerate

   always @ (posedge clk) begin
      if (~reset & stfin) begin
	 data[finptr] <= stdata;
	 addr[finptr] <= staddr;
	 spectag[finptr] <= stspectag;
      end
   end
   
   always @ (posedge clk) begin
      if (reset) begin
	 finptr <= 0;
	 comptr <= 0;
	 retptr <= 0;
	 valid <= 0;
	 completed <= 0;
      end else if (prmiss) begin
	 if (stfin) begin
	    //KillNotOccur!!!
	    finptr <= finptr + 1;
	    valid[finptr] <= 1'b1;
	    completed[finptr] <= 1'b0;
	    comptr <= comptr;
	    retptr <= retptr;
	 end else begin
	    valid <= valid & valid_cls;
	    finptr <= finptr_next;
	    comptr <= ~notempty_next ? finptr : comptr;
	    retptr <= ~notempty_next ? finptr : retptr;
	 end
      end else begin
	 if (stfin) begin
	    finptr <= finptr + 1;
	    valid[finptr] <= 1'b1;
	    completed[finptr] <= 1'b0;
	 end
	 if (stcom) begin
	    comptr <= comptr + 1;
	    completed[comptr] <= 1'b1;
	 end
	 if (stretire) begin
	    retptr <= retptr + 1;
	    valid[retptr] <= 1'b0;
	    completed[retptr] <= 1'b0;
	 end
      end
   end // always @ (posedge clk)

   always @ (posedge clk) begin
      if (reset | prmiss) begin
	 specbit <= 0;
      end else if (prsuccess) begin
	 specbit <= (specbit & specbit_cls) |
		    (stfin ? 
		     ({`STBUF_ENT_NUM{stspecbit}} << finptr) : 
		     `STBUF_ENT_NUM'b0);
      end else begin
	 if (stfin) begin
	    specbit[finptr] <= stspecbit;
	 end
      end
   end
endmodule // storebuf
/**************************************************************************************************/
/* Many-core processor project Arch Lab.                                               TOKYO TECH */
/**************************************************************************************************/
`default_nettype none
/**************************************************************************************************/
`include "define.v"
/**************************************************************************************************/

module CLKGEN_DCM(CLK_IN, CLK_OUT, LOCKED);
    input wire  CLK_IN;
    output wire CLK_OUT, LOCKED;

    wire clk_ibuf;
    wire clk_out;
    wire clk0, clk0_fbuf;

    // input buffer
    IBUFG ibuf (.I(CLK_IN),
                .O(clk_ibuf));
    // output buffer
    BUFG  obuf (.I(clk_out),
                .O(CLK_OUT));
    // feedback buffer
    BUFG  fbuf (.I(clk0),
                .O(clk0_fbuf));

    // dcm instantiation
    DCM_SP dcm (// input
                .CLKIN   (clk_ibuf),
                .RST     (1'b0),
                // output
                .CLKFX   (clk_out),
                .LOCKED  (LOCKED),
                // feedback
                .CLK0    (clk0),
                .CLKFB   (clk0_fbuf), 
                // phase shift
                .PSEN    (1'b0),
                .PSINCDEC(1'b0),
                .PSCLK   (1'b0),
                // digital spread spectrum
                .DSSEN   (1'b0));

    defparam dcm.CLKIN_PERIOD   = `DCM_CLKIN_PERIOD;
    defparam dcm.CLKFX_MULTIPLY = `DCM_CLKFX_MULTIPLY;
    defparam dcm.CLKFX_DIVIDE   = `DCM_CLKFX_DIVIDE;
endmodule

/**************************************************************************************************/

module CLKGEN_MMCM(CLK_IN, CLK_OUT, LOCKED);
    input wire  CLK_IN;
    output wire CLK_OUT, LOCKED;

    wire clk_out;
    wire clkfb, clkfb_fbuf;

    // output buffer
    BUFG  obuf (.I(clk_out),
                .O(CLK_OUT));
    // feedback buffer
    BUFG  fbuf (.I(clkfb),
                .O(clkfb_fbuf));

    MMCME2_ADV mmcm (// input
				     .CLKIN1       (CLK_IN),
				     .CLKIN2       (1'b0),
				     .CLKINSEL     (1'b1),
				     .RST          (1'b0),
				     .PWRDWN       (1'b0),
				  	 // output
				     .CLKOUT0      (clk_out),
				     .CLKOUT0B     (),
				     .CLKOUT1      (),
				     .CLKOUT1B     (),
				     .CLKOUT2      (),
				     .CLKOUT2B     (),
				     .CLKOUT3      (),
				     .CLKOUT3B     (),
				     .CLKOUT4      (),
				     .CLKOUT5      (),
				     .CLKOUT6      (),
				     .LOCKED       (LOCKED),
                     // feedback
				     .CLKFBOUT     (clkfb),
				     .CLKFBIN      (clkfb_fbuf),
				     .CLKFBOUTB    (),
				     // dynamic reconfiguration
				     .DADDR        (7'h0),
				     .DI           (16'h0),
				     .DWE          (1'b0),
				     .DEN          (1'b0),
				     .DCLK         (1'b0),
				     .DO           (),
				     .DRDY         (),
				     // phase shift
				     .PSCLK        (1'b0),
				     .PSEN         (1'b0),
				     .PSINCDEC     (1'b0),
				     .PSDONE       (),
				     // status
				     .CLKINSTOPPED (),
				     .CLKFBSTOPPED ());

    defparam mmcm.CLKIN1_PERIOD    = `MMCM_CLKIN1_PERIOD;
    defparam mmcm.CLKFBOUT_MULT_F  = `MMCM_VCO_MULTIPLY;
    defparam mmcm.DIVCLK_DIVIDE    = `MMCM_VCO_DIVIDE;
    defparam mmcm.CLKOUT0_DIVIDE_F = `MMCM_CLKOUT0_DIVIDE;
    defparam mmcm.CLKOUT1_DIVIDE   = `MMCM_CLKOUT1_DIVIDE;
endmodule

/**************************************************************************************************/

module RSTGEN(CLK, RST_X_I, RST_X_O);
    input wire  CLK, RST_X_I;
    output wire RST_X_O;

    reg [7:0] cnt;
    assign RST_X_O = cnt[7];

    always @(posedge CLK or negedge RST_X_I) begin
        if      (!RST_X_I) cnt <= 0;
        else if (~RST_X_O) cnt <= (cnt + 1'b1);
    end
endmodule

/**************************************************************************************************/

module GEN_DCM(CLK_I, RST_X_I, CLK_O, RST_X_O);
    input wire  CLK_I, RST_X_I;
    output wire CLK_O, RST_X_O;
    
    wire LOCKED;
    
    CLKGEN_DCM clkgen(.CLK_IN (CLK_I),
                      .CLK_OUT(CLK_O),
                      .LOCKED (LOCKED));
    RSTGEN     rstgen(.CLK    (CLK_O),
                      .RST_X_I(RST_X_I & LOCKED),
                      .RST_X_O(RST_X_O));
endmodule

module GEN_MMCM(CLK_I, RST_X_I, CLK_O, RST_X_O);
    input wire  CLK_I, RST_X_I;
    output wire CLK_O, RST_X_O;
    
    wire clk_ibuf;
    wire LOCKED;

    // input buffer
    IBUFG ibuf (.I(CLK_I),
                .O(clk_ibuf));

    CLKGEN_MMCM clkgen(.CLK_IN (clk_ibuf),
                       .CLK_OUT(CLK_O),
                       .LOCKED (LOCKED));
    RSTGEN      rstgen(.CLK    (CLK_O),
                       .RST_X_I(RST_X_I & LOCKED),
                       .RST_X_O(RST_X_O));
endmodule

module GEN_MMCM_DS(CLK_P, CLK_N, RST_X_I, CLK_O, RST_X_O);
    input wire  CLK_P, CLK_N, RST_X_I;
    output wire CLK_O, RST_X_O;

    wire clk_ibuf;
    wire LOCKED;

    // input buffer
    IBUFGDS ibuf (.I (CLK_P),
                  .IB(CLK_N),
                  .O (clk_ibuf));

    CLKGEN_MMCM clkgen(.CLK_IN (clk_ibuf),
                       .CLK_OUT(CLK_O),
                       .LOCKED (LOCKED));
    RSTGEN      rstgen(.CLK    (CLK_O),
                       .RST_X_I(RST_X_I & LOCKED),
                       .RST_X_O(RST_X_O));
endmodule

/**************************************************************************************************/
`default_nettype wire
/**************************************************************************************************/
`include "constants.vh"
`default_nettype none
module tag_generator(
		     input wire 		    clk,
		     input wire 		    reset,
		     input wire 		    branchvalid1,    //inst1是否有效
		     input wire 		    branchvalid2,    //inst2是否有效
		     input wire 		    prmiss,
		     input wire 		    prsuccess,       //预测成功
		     input wire 		    enable,          //指令是否可以发射
		     input wire [`SPECTAG_LEN-1:0]  tagregfix,

		     output wire [`SPECTAG_LEN-1:0] sptag1,		//speculative tag  00001、00010、…、10000（从 00001 左循环）的顺序
		     output wire [`SPECTAG_LEN-1:0] sptag2, 	//speculative tag
		     output wire 		    speculative1,
		     output wire 		    speculative2,
			 //如果没有可用的推测标签，标签产生器将把 attachable 标志设置为 0，并暂停标签指派流程。
		     output wire 		    attachable,
		     output reg [`SPECTAG_LEN-1:0]  tagreg
		     );

//    reg [`SPECTAG_LEN-1:0] 		       tagreg;

   // tagereg 推测标签寄存器
   // brdepth 分支深度寄存器
   reg [`BRDEPTH_LEN-1:0] 		       brdepth;
   
   // 左循环
   assign sptag1 = (branchvalid1) ? 
		   {tagreg[`SPECTAG_LEN-2:0], tagreg[`SPECTAG_LEN-1]}
		   : tagreg;
   assign sptag2 = (branchvalid2) ? 
		   {sptag1[`SPECTAG_LEN-2:0], sptag1[`SPECTAG_LEN-1]}
		   : sptag1;
	// depth != 0 则开始推测
   assign speculative1 = (brdepth != 0) ? 1'b1 : 1'b0;
   assign speculative2 = ((brdepth != 0) || branchvalid1) ? 1'b1 : 1'b0;
   //
   assign attachable = (brdepth + branchvalid1 + branchvalid2) > (`BRANCH_ENT_NUM + prsuccess) ? 1'b0 : 1'b1;

   // 根据 prmiss 和 enable 来更新 tagreg 和 brdepth
   always @ (posedge clk) begin
      if (reset) begin
	 tagreg <= `SPECTAG_LEN'b1;
	 brdepth <= `BRDEPTH_LEN'b0;
      end else begin
	 tagreg <= prmiss ? tagregfix :
		   ~enable ? tagreg : 
		   sptag2;
	 brdepth <= prmiss ? `BRDEPTH_LEN'b0 :
		    ~enable ? brdepth - prsuccess :
		    brdepth + branchvalid1 + branchvalid2 - prsuccess;
      end
   end
   
endmodule // tag_generator
`default_nettype wire
`include "define.v"
`include "constants.vh"

module top
  (
//   input 	    CLK_P,
//   input 	    CLK_N,
//   input 	    RST_X_IN,
//   output 	    TXD,
//   input 	    RXD,
//   output reg [7:0] LED
   input clk,
   input reset_x
   );

   //Active Low SW
//   wire 	    clk;
//   wire 	    reset_x;


   wire [`ADDR_LEN-1:0] pc;
   wire [4*`INSN_LEN-1:0] idata;
   wire [8:0] 		  imem_addr;
   wire [`DATA_LEN-1:0]   dmem_data;
   wire [`DATA_LEN-1:0]   dmem_wdata;
   wire [`ADDR_LEN-1:0]   dmem_addr;
   wire 		  dmem_we;
   wire [`DATA_LEN-1:0]   dmem_wdata_core;
   wire [`ADDR_LEN-1:0]   dmem_addr_core;
   wire 		  dmem_we_core;

   wire 		  utx_we;
   wire 		  finish_we;
   wire 		  ready_tx;
   wire 		  loaded;
   
   reg 			  prog_loading;
   wire [4*`INSN_LEN-1:0] prog_loaddata = 0;
   wire [`ADDR_LEN-1:0]   prog_loadaddr = 0;
   wire 		  prog_dmem_we = 0;
   wire 		  prog_imem_we = 0;
/*   
   assign utx_we = (dmem_we_core && (dmem_addr_core == 32'h0)) ? 1'b1 : 1'b0;
   assign finish_we = (dmem_we_core && (dmem_addr_core == 32'h8)) ? 1'b1 : 1'b0;
   
   always @ (posedge clk) begin
      if (!reset_x) begin
	 LED <= 0;
      end else if (utx_we) begin
	 LED <= {LED[7], dmem_wdata[6:0]};
      end else if (finish_we) begin
	 LED <= {1'b1, LED[6:0]};
      end
   end
*/
   always @ (posedge clk) begin
      if (!reset_x) begin
	 prog_loading <= 1'b1;
      end else begin
	 prog_loading <= 0;
      end
   end
/*   
   GEN_MMCM_DS genmmcmds
     (
      .CLK_P(CLK_P), 
      .CLK_N(CLK_N), 
      .RST_X_I(~RST_X_IN), 
      .CLK_O(clk), 
      .RST_X_O(reset_x)
      );
*/
   pipeline pipe
     (
      .clk(clk),
      .reset(~reset_x | prog_loading),
      .pc(pc),
      .idata(idata),
      .dmem_wdata(dmem_wdata_core),
      .dmem_addr(dmem_addr_core),
      .dmem_we(dmem_we_core),
      .dmem_data(dmem_data)
      );

   assign dmem_addr = prog_loading ? prog_loadaddr : dmem_addr_core;
   assign dmem_we = prog_loading ? prog_dmem_we : dmem_we_core;
   assign dmem_wdata = prog_loading ? prog_loaddata[127:96] : dmem_wdata_core;
   dmem datamemory(
		   .clk(clk),
		   .addr({2'b0, dmem_addr[`ADDR_LEN-1:2]}),
		   .wdata(dmem_wdata),
		   .we(dmem_we),
		   .rdata(dmem_data)
		   );

   assign imem_addr = prog_loading ? prog_loadaddr[12:4] : pc[12:4];
   imem_ld instmemory(
		      .clk(~clk),
		      .addr(imem_addr),
		      .rdata(idata),
		      .wdata(prog_loaddata),
		      .we(prog_imem_we)
		      );
/*   
   SingleUartTx sutx
     (
      .CLK(clk),
      .RST_X(reset_x),
      .TXD(TXD),
      .ERR(),
      .DT01(dmem_wdata[7:0]),
      .WE01(utx_we)
      );

   PLOADER loader
     (
      .CLK(clk),
      .RST_X(reset_x),
      .RXD(RXD),
      .ADDR(prog_loadaddr),
      .DATA(prog_loaddata),
      .WE_32(prog_dmem_we),
      .WE_128(prog_imem_we),
      .DONE(loaded)
      );
*/   
endmodule // top

   
`include "define.v"
`include "constants.vh"

module top
  (
   input 	    CLK_P,
   input 	    CLK_N,
   input 	    RST_X_IN,
   output 	    TXD,
   input 	    RXD,
   output reg [7:0] LED
   );

   //Active Low SW
   wire 	    clk;
   wire 	    reset_x;


   wire [`ADDR_LEN-1:0] pc;
   wire [4*`INSN_LEN-1:0] idata;
   wire [8:0] 		  imem_addr;
   wire [`DATA_LEN-1:0]   dmem_data;
   wire [`DATA_LEN-1:0]   dmem_wdata;
   wire [`ADDR_LEN-1:0]   dmem_addr;
   wire 		  dmem_we;
   wire [`DATA_LEN-1:0]   dmem_wdata_core;
   wire [`ADDR_LEN-1:0]   dmem_addr_core;
   wire 		  dmem_we_core;

   wire 		  utx_we;
   wire 		  finish_we;
   reg 			  finished;
   wire 		  ready_tx;
   wire 		  loaded;
   
   reg 			  prog_loading;
   wire [4*`INSN_LEN-1:0] prog_loaddata;
   wire [`ADDR_LEN-1:0]   prog_loadaddr;
   wire 		  prog_dmem_we;
   wire 		  prog_imem_we;
   
   assign utx_we = (~finished && dmem_we_core && (dmem_addr_core == 32'h0)) ? 1'b1 : 1'b0;
   assign finish_we = (dmem_we_core && (dmem_addr_core == 32'h8)) ? 1'b1 : 1'b0;
   
   always @ (posedge clk) begin
      if (!reset_x) begin
	 LED <= 0;
      end else if (utx_we) begin
	 LED <= {LED[7], dmem_wdata[6:0]};
      end else if (finish_we) begin
	 LED <= {1'b1, LED[6:0]};
      end
   end

   always @ (posedge clk) begin
      if (!reset_x) begin
	 prog_loading <= 1'b1;
      end else begin
	 prog_loading <= ~loaded;
      end
   end

   always @ (posedge clk) begin
      if (!reset_x) begin
	 finished <= 0;
      end else if (finish_we) begin
	 finished <= 1;
      end
   end
   
   GEN_MMCM_DS genmmcmds
     (
      .CLK_P(CLK_P), 
      .CLK_N(CLK_N), 
      .RST_X_I(~RST_X_IN), 
      .CLK_O(clk), 
      .RST_X_O(reset_x)
      );

   pipeline pipe
     (
      .clk(clk),
      .reset(~reset_x | prog_loading),
      .pc(pc),
      .idata(idata),
      .dmem_wdata(dmem_wdata_core),
      .dmem_addr(dmem_addr_core),
      .dmem_we(dmem_we_core),
      .dmem_data(dmem_data)
      );

   assign dmem_addr = prog_loading ? prog_loadaddr : dmem_addr_core;
   assign dmem_we = prog_loading ? prog_dmem_we : dmem_we_core;
   assign dmem_wdata = prog_loading ? prog_loaddata[127:96] : dmem_wdata_core;
   dmem datamemory(
		   .clk(clk),
		   .addr({2'b0, dmem_addr[`ADDR_LEN-1:2]}),
		   .wdata(dmem_wdata),
		   .we(dmem_we),
		   .rdata(dmem_data)
		   );

   assign imem_addr = prog_loading ? prog_loadaddr[12:4] : pc[12:4];
   imem_ld instmemory(
		      .clk(~clk),
		      .addr(imem_addr),
		      .rdata(idata),
		      .wdata(prog_loaddata),
		      .we(prog_imem_we)
		      );
   
   SingleUartTx sutx
     (
      .CLK(clk),
      .RST_X(reset_x),
      .TXD(TXD),
      .ERR(),
      .DT01(dmem_wdata[7:0]),
      .WE01(utx_we)
      );

   PLOADER loader
     (
      .CLK(clk),
      .RST_X(reset_x),
      .RXD(RXD),
      .ADDR(prog_loadaddr),
      .DATA(prog_loaddata),
      .WE_32(prog_dmem_we),
      .WE_128(prog_imem_we),
      .DONE(loaded)
      );
   
endmodule // top

   
/**************************************************************************************************/
/* Many-core processor project Arch Lab.                                               TOKYO TECH */
/**************************************************************************************************/
`default_nettype none
  /**************************************************************************************************/
`include "define.v"
  /**************************************************************************************************/
`define SS_SER_WAIT  'd0       // do not modify this. RS232C deserializer, State WAIT
`define SS_SER_RCV0  'd1       // do not modify this. RS232C deserializer, State Receive0
`define SS_SER_DONE  'd9       // do not modify this. RS232C deserializer, State DONE
  /**************************************************************************************************/
  /*
   module UartTx(CLK, RST_X, DATA, WE, TXD, READY);
   input  wire        CLK, RST_X, WE;
   input  wire [15:0] DATA;
   output reg         TXD, READY;

   reg [18:0]   cmd;
   reg [11:0]   waitnum;
   reg [4:0]    cnt;

   always @(posedge CLK or negedge RST_X) begin
   if(~RST_X) begin
   TXD       <= 1'b1;
   READY     <= 1'b1;
   cmd       <= 19'h7ffff;
   waitnum   <= 0;
   cnt       <= 0;
        end else if( READY ) begin
   TXD       <= 1'b1;
   waitnum   <= 0;
   if( WE )begin
   READY <= 1'b0;
   //cmd   <= {DATA[15:8], 2'b01, DATA[7:0], 1'b0};
   cmd   <= {DATA[15:8], 2'b01, 8'b11111111, 1'b1};
   cnt   <= 20;  // 10
            end
        end else if( waitnum >= `SERIAL_WCNT ) begin
   TXD       <= cmd[0];
   READY     <= (cnt == 1);
   cmd       <= {1'b1, cmd[18:1]};
   waitnum   <= 1;
   cnt       <= cnt - 1;
        end else begin
   waitnum   <= waitnum + 1;
        end
    end
   endmodule
   */

  module UartTx(CLK, RST_X, DATA, WE, TXD, READY);
   input wire  CLK, RST_X, WE;
   input wire [7:0] DATA;
   output reg  TXD, READY;

   reg [8:0]   cmd;
   reg [11:0]  waitnum;
   reg [3:0]   cnt;

   always @(posedge CLK or negedge RST_X) begin
      if(~RST_X) begin
         TXD       <= 1'b1;
         READY     <= 1'b1;
         cmd       <= 9'h1ff;
         waitnum   <= 0;
         cnt       <= 0;
      end else if( READY ) begin
         TXD       <= 1'b1;
         waitnum   <= 0;
         if( WE )begin
            READY <= 1'b0;
            cmd   <= {DATA, 1'b0};
            cnt   <= 10;
         end
      end else if( waitnum >= `SERIAL_WCNT ) begin
         TXD       <= cmd[0];
         READY     <= (cnt == 1);
         cmd       <= {1'b1, cmd[8:1]};
         waitnum   <= 1;
         cnt       <= cnt - 1;
      end else begin
         waitnum   <= waitnum + 1;
      end
   end
endmodule

/**************************************************************************************************/

module TX_FIFO(CLK, RST_X, D_IN, WE, RE, D_OUT, D_EN, RDY, ERR);
   input  wire       CLK, RST_X, WE, RE;
   input  wire [7:0] D_IN;
   output reg [7:0]  D_OUT;
   output reg        D_EN, ERR;
   output wire       RDY;
   
   reg [7:0] 	     mem [0:2048-1]; // FIFO memory
   reg [10:0] 	     head, tail;    // regs for FIFO 
   
   assign RDY = (D_EN==0 && head!=tail);
   
   always @(posedge CLK) begin
      if(~RST_X) begin 
         {D_EN, ERR, head, tail, D_OUT} <= 0;
      end
      else begin            
         if(WE) begin  ///// enqueue
            mem[tail] <= D_IN;
            tail <= tail + 1;
            if(head == (tail + 1)) ERR <= 1; // buffer may full!
         end
         
         if(RE) begin  ///// dequeue   
            D_OUT <= mem[head];
            D_EN  <= 1;
            head <= head + 1;
         end else begin
            D_EN <= 0;
         end
      end
   end
endmodule

/**************************************************************************************************/
/*
 module MultiUartTx(CLK, RST_X, TXD, ERR, 
 DT01, WE01, DT02, WE02, DT03, WE03, DT04, WE04);
 input  wire       CLK, RST_X;
 input  wire [7:0] DT01, DT02, DT03, DT04;
 input  wire       WE01, WE02, WE03, WE04;
 output wire       TXD, ERR;
 
 wire RE01, RE02, RE03, RE04;
 wire [7:0] data01, data02, data03, data04;
 wire en01, en02, en03, en04;
 wire RDY01, RDY02, RDY03, RDY04;
 wire ERR01, ERR02, ERR03, ERR04;
 wire [15:0] data;
 wire en;
 wire TxRdy;

 assign ERR = ERR01 | ERR02 | ERR03 | ERR04;
 assign RE01 = (RDY01 & TxRdy);
 assign RE02 = (RDY02 & TxRdy) & (~RDY01 & ~en01);
 assign RE03 = (RDY03 & TxRdy) & (~RDY01 & ~en01) & (~RDY02 & ~en02);
 assign RE04 = (RDY04 & TxRdy) & (~RDY01 & ~en01) & (~RDY02 & ~en02) & (~RDY03 & ~en03);
 
 assign data = (en01) ? {data01, 8'h30} : 
 (en02) ? {data02, 8'h31} :
 (en03) ? {data03, 8'h32} : {data04, 8'h33};
 assign en = en01 | en02 | en03 | en04;

 TX_FIFO fifo_01(CLK, RST_X, DT01, WE01, RE01, data01, en01, RDY01, ERR01); 
 TX_FIFO fifo_02(CLK, RST_X, DT02, WE02, RE02, data02, en02, RDY02, ERR02); 
 TX_FIFO fifo_03(CLK, RST_X, DT03, WE03, RE03, data03, en03, RDY03, ERR03); 
 TX_FIFO fifo_04(CLK, RST_X, DT04, WE04, RE04, data04, en04, RDY04, ERR04); 
 UartTx send(CLK, RST_X, data, en, TXD, TxRdy);
 endmodule
 */
module SingleUartTx(CLK, RST_X, TXD, ERR, DT01, WE01);
   input  wire       CLK, RST_X;
   input  wire [7:0] DT01;
   input  wire 	     WE01;
   output wire 	     TXD, ERR;
   
   wire 	     RE01;
   wire [7:0] 	     data01;
   wire 	     en01;
   wire 	     RDY01;
   wire 	     ERR01;
   wire 	     TxRdy;

   assign ERR = ERR01;
   assign RE01 = (RDY01 & TxRdy);

   TX_FIFO fifo_01(CLK, RST_X, DT01, WE01, RE01, data01, en01, RDY01, ERR01); 
   UartTx send(CLK, RST_X, data01, en01, TXD, TxRdy);
endmodule


/**************************************************************************************************/

module UartRx(CLK, RST_X, RXD, DATA, EN);
   input  wire       CLK, RST_X, RXD; // clock, reset, RS232C input
   output reg [7:0]  DATA;            // 8bit output data
   output reg        EN;              // 8bit output data enable

   reg [3:0] 	     stage;
   reg [12:0] 	     cnt;             // counter to latch D0, D1, ..., D7
   reg [11:0] 	     cnt_start;       // counter to detect the Start Bit
   wire [12:0] 	     waitcnt;

   assign waitcnt = `SERIAL_WCNT;

   always @(posedge CLK or negedge RST_X)
     if (~RST_X) cnt_start <= 0;
     else        cnt_start <= (RXD) ? 0 : cnt_start + 1;

   always @(posedge CLK or negedge RST_X)
     if(~RST_X) begin
        EN     <= 0;
        stage  <= `SS_SER_WAIT;
        cnt    <= 1;
        DATA   <= 0;
     end else if (stage == `SS_SER_WAIT) begin // detect the Start Bit
        EN <= 0;
        stage <= (cnt_start == (waitcnt >> 1)) ? `SS_SER_RCV0 : stage;
     end else begin
        if (cnt != waitcnt) begin
           cnt <= cnt + 1;
           EN <= 0;
        end else begin // receive 1bit data
           stage  <= (stage == `SS_SER_DONE) ? `SS_SER_WAIT : stage + 1;
           EN     <= (stage == 8)  ? 1 : 0;
           DATA   <= {RXD, DATA[7:1]};
           cnt <= 1;
        end
     end
endmodule

/**************************************************************************************************/
/*
module PLOADER(CLK, RST_X, RXD, ADDR, DATA, WE, DONE1, DONE2);
   input  wire       CLK, RST_X, RXD;
   output reg [31:0] ADDR;
   output reg [31:0] DATA;
   output reg        WE;
   output reg        DONE1; // application program load is done
   output reg        DONE2; // scheduling program load is done

   reg [31:0] 	     waddr; // memory write address

   wire 	     SER_EN;
   wire [7:0] 	     SER_DATA;
   
   UartRx recv(CLK, RST_X, RXD, SER_DATA, SER_EN);

   always @(posedge CLK or negedge RST_X) begin
      if(~RST_X) begin
         {ADDR, DATA, WE, waddr, DONE1, DONE2} <= 0;
      end else begin
         if(DONE2==0 && SER_EN) begin
            //ADDR  <= (waddr<32'h40000) ? waddr : {8'h04, 6'd0, waddr[17:0]};
            ADDR  <= waddr;            
            DATA  <= {SER_DATA, DATA[31:8]};
            WE    <= (waddr[1:0]==3);
            waddr <= waddr + 1;
            if(waddr>=`APP_SIZE) DONE1 <= 1;
         end else begin
            WE <= 0;
            if(waddr>=`APP_SIZE) DONE1 <= 1;
            if(waddr>=`IMG_SIZE) DONE2 <= 1;
         end
      end
   end
endmodule
*/

module PLOADER(CLK, RST_X, RXD, ADDR, DATA, WE_32, WE_128, DONE);
   input  wire       CLK, RST_X, RXD;
   output reg [31:0] ADDR;
   output reg [127:0] DATA;
   output reg        WE_32;
   output reg 	     WE_128;
   output reg        DONE;

   reg [31:0] 	     waddr; // memory write address

   wire 	     SER_EN;
   wire [7:0] 	     SER_DATA;
   
   UartRx recv(CLK, RST_X, RXD, SER_DATA, SER_EN);

   always @(posedge CLK or negedge RST_X) begin
      if(~RST_X) begin
         {ADDR, DATA, WE_32, WE_128, waddr, DONE} <= 0;
      end else begin
         if(DONE==0 && SER_EN) begin
            ADDR   <= waddr;            
            DATA   <= {SER_DATA, DATA[127:8]};
            WE_32  <= (waddr[1:0]==3) ? 1'b1 : 1'b0;
	    WE_128 <= (waddr[3:0]==15) ? 1'b1 : 1'b0;
            waddr <= waddr + 1;
            if(waddr>=`APP_SIZE) DONE <= 1;
         end else begin
            WE_32 <= 0;
	    WE_128 <= 0;
            if(waddr>=`APP_SIZE) DONE <= 1;
         end
      end
   end
endmodule

/**************************************************************************************************/
`default_nettype wire
  /**************************************************************************************************/
